1 /* $NetBSD: partman.c,v 1.41 2019/07/25 19:01:08 martin 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", dev_ptr->nsectors); 954 wprintw(m->mw, "%*s %s", -lcol_width, 955 msg_string(MSG_vnd_spt_fmt), buf); 956 break; 957 case PMV_MENU_NTRACKS: 958 if (dev_ptr->manual_geom && !dev_ptr->is_exist) 959 snprintf(buf, SSTRSIZE, "%d", dev_ptr->ntracks); 960 wprintw(m->mw, "%*s %s", -lcol_width, 961 msg_string(MSG_vnd_tpc_fmt), buf); 962 break; 963 case PMV_MENU_NCYLINDERS: 964 if (dev_ptr->manual_geom && !dev_ptr->is_exist) 965 snprintf(buf, SSTRSIZE, "%d", dev_ptr->ncylinders); 966 wprintw(m->mw, "%*s %s", -lcol_width, 967 msg_string(MSG_vnd_cyl_fmt), buf); 968 break; 969 } 970 } 971 972 static int 973 pm_vnd_set_value(menudesc *m, void *arg) 974 { 975 struct vnd_desc *dev_ptr = arg; 976 char buf[STRSIZE]; 977 const char *msg_to_show = NULL; 978 int *out_var = NULL; 979 980 switch (m->cursel) { 981 case PMV_MENU_FILEPATH: 982 msg_prompt_win(MSG_vnd_path_ask, -1, 18, 0, 0, 983 dev_ptr->filepath, dev_ptr->filepath, STRSIZE); 984 if (dev_ptr->filepath[0] != '/') { 985 strlcpy(buf, dev_ptr->filepath, MOUNTLEN); 986 snprintf(dev_ptr->filepath, MOUNTLEN, "/%s", buf); 987 } 988 if (dev_ptr->filepath[strlen(dev_ptr->filepath) - 1] == '/') 989 dev_ptr->filepath[strlen(dev_ptr->filepath) - 1] = '\0'; 990 return 0; 991 case PMV_MENU_EXIST: 992 dev_ptr->is_exist = !dev_ptr->is_exist; 993 return 0; 994 case PMV_MENU_SIZE: 995 if (dev_ptr->is_exist) 996 return 0; 997 998 pm_edit_size_value(MSG_vnd_size_ask, pm->dlcylsize, 999 &dev_ptr->size); 1000 1001 break; 1002 case PMV_MENU_RO: 1003 dev_ptr->readonly = !dev_ptr->readonly; 1004 return 0; 1005 case PMV_MENU_MGEOM: 1006 if (dev_ptr->is_exist) 1007 return 0; 1008 dev_ptr->manual_geom = !dev_ptr->manual_geom; 1009 return 0; 1010 case PMV_MENU_SECSIZE: 1011 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1012 return 0; 1013 msg_to_show = MSG_vnd_bps_ask; 1014 out_var = &(dev_ptr->secsize); 1015 break; 1016 case PMV_MENU_NSECTORS: 1017 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1018 return 0; 1019 msg_to_show = MSG_vnd_spt_ask; 1020 out_var = &(dev_ptr->nsectors); 1021 break; 1022 case PMV_MENU_NTRACKS: 1023 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1024 return 0; 1025 msg_to_show = MSG_vnd_tpc_ask; 1026 out_var = &(dev_ptr->ntracks); 1027 break; 1028 case PMV_MENU_NCYLINDERS: 1029 if (!dev_ptr->manual_geom || dev_ptr->is_exist) 1030 return 0; 1031 msg_to_show = MSG_vnd_cyl_ask; 1032 out_var = &(dev_ptr->ncylinders); 1033 break; 1034 case PMV_MENU_REMOVE: 1035 dev_ptr->enabled = 0; 1036 return 0; 1037 } 1038 if (out_var == NULL || msg_to_show == NULL) 1039 return -1; 1040 snprintf(buf, SSTRSIZE, "%d", *out_var); 1041 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 1042 if (atoi(buf) >= 0) 1043 *out_var = atoi(buf); 1044 return 0; 1045 } 1046 1047 static void 1048 pm_vnd_init(void *arg, void *none) 1049 { 1050 struct vnd_desc *dev_ptr = arg; 1051 memset(dev_ptr, 0, sizeof(*dev_ptr)); 1052 *dev_ptr = (struct vnd_desc) { 1053 .enabled = 1, 1054 .blocked = 0, 1055 .filepath[0] = '\0', 1056 .is_exist = 0, 1057 .size = 1024, 1058 .readonly = 0, 1059 .manual_geom = 0, 1060 .secsize = 512, 1061 .nsectors = 18, 1062 .ntracks = 2, 1063 .ncylinders = 80 1064 }; 1065 } 1066 1067 static int 1068 pm_vnd_check(void *arg) 1069 { 1070 struct vnd_desc *dev_ptr = arg; 1071 1072 if (dev_ptr->blocked) 1073 return 0; 1074 if (strlen(dev_ptr->filepath) < 1 || 1075 dev_ptr->size < 1) 1076 dev_ptr->enabled = 0; 1077 else { 1078 pm_manage_getfreenode(&(dev_ptr->node), "vnd", &vnds_t_info); 1079 if (dev_ptr->node < 0) 1080 dev_ptr->enabled = 0; 1081 } 1082 return dev_ptr->enabled; 1083 } 1084 1085 /* XXX: vndconfig always return 0? */ 1086 static int 1087 pm_vnd_commit(void) 1088 { 1089 int i, error; 1090 char r_o[3], buf[MOUNTLEN+3], resultpath[STRSIZE]; 1091 const char *mpath, *mp_suit = NULL, *rp; 1092 struct pm_devs *pm_i, *pm_suit = NULL; 1093 part_id id, part_suit = NO_PART; 1094 struct disk_part_info info; 1095 1096 for (i = 0; i < MAX_VND; i++) { 1097 error = 0; 1098 if (! pm_vnd_check(&vnds[i])) 1099 continue; 1100 1101 /* Trying to assign target device */ 1102 SLIST_FOREACH(pm_i, &pm_head, l) { 1103 for (id = 0; id < pm_i->parts->num_part; id++) { 1104 if (!pm_i->parts->pscheme->get_part_info( 1105 pm_i->parts, id, &info)) 1106 continue; 1107 if (info.flags & (PTI_SEC_CONTAINER| 1108 PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL| 1109 PTI_RAW_PART)) 1110 continue; 1111 if (info.last_mounted == NULL || 1112 info.last_mounted[0] == 0) 1113 continue; 1114 mpath = info.last_mounted; 1115 strcpy(buf, mpath); 1116 if (buf[strlen(buf)-1] != '/') 1117 strcat(buf, "/"); 1118 if (strstr(vnds[i].filepath, buf) != 1119 vnds[i].filepath) 1120 continue; 1121 if (part_suit == NO_PART || pm_suit == NULL || 1122 strlen(buf) > strlen(mp_suit)) { 1123 part_suit = id; 1124 pm_suit = pm_i; 1125 mp_suit = mpath; 1126 } 1127 } 1128 } 1129 if (part_suit == NO_PART || pm_suit == NULL || 1130 mp_suit == NULL) 1131 continue; 1132 1133 /* Mounting assigned partition and try to get real file path*/ 1134 if (pm_mount(pm_suit, part_suit) != 0) 1135 continue; 1136 rp = pm_get_mount(pm_suit, part_suit); 1137 snprintf(resultpath, STRSIZE, "%s/%s", 1138 rp, 1139 &(vnds[i].filepath[strlen(rp)])); 1140 1141 strcpy(r_o, vnds[i].readonly?"-r":""); 1142 /* If this is a new image */ 1143 if (!vnds[i].is_exist) { 1144 run_program(RUN_DISPLAY | RUN_PROGRESS, "mkdir -p %s ", 1145 dirname(resultpath)); 1146 if (error == 0) 1147 error = run_program(RUN_DISPLAY | RUN_PROGRESS, 1148 "dd if=/dev/zero of=%s bs=1m " 1149 "count=% " PRIi64 " progress=100 " 1150 "msgfmt=human", 1151 resultpath, vnds[i].size*(MEG/512)); 1152 } 1153 if (error) 1154 continue; 1155 1156 /* If this is a new image with manual geometry */ 1157 if (!vnds[i].is_exist && vnds[i].manual_geom) 1158 error = run_program(RUN_DISPLAY | RUN_PROGRESS, 1159 "vndconfig %s vnd%d %s %d %d %d %d", 1160 r_o, vnds[i].node, 1161 resultpath, vnds[i].secsize, 1162 vnds[i].nsectors, 1163 vnds[i].ntracks, vnds[i].ncylinders); 1164 else 1165 /* If this is a existing image or image without manual 1166 * geometry */ 1167 error = run_program(RUN_DISPLAY | RUN_PROGRESS, 1168 "vndconfig %s vnd%d %s", 1169 r_o, vnds[i].node, resultpath); 1170 1171 if (error == 0) { 1172 vnds[i].blocked = 1; 1173 vnds[i].pm_part = part_suit; 1174 vnds[i].pm = pm_suit; 1175 vnds[i].pm->blocked++; 1176 } 1177 } 1178 return 0; 1179 } 1180 1181 /*** 1182 CGD 1183 ***/ 1184 1185 static void 1186 pm_cgd_menufmt(menudesc *m, int opt, void *arg) 1187 { 1188 struct cgd_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 1189 char desc[STRSIZE]; 1190 struct disk_part_info info; 1191 1192 if (dev_ptr->enabled == 0) 1193 return; 1194 if (dev_ptr->pm == NULL) 1195 wprintw(m->mw, "%s", msg_string(MSG_cgd_err_menufmt)); 1196 else { 1197 snprintf(desc, sizeof desc, "cgd%d (%s-%d)", 1198 dev_ptr->node, dev_ptr->enc_type, dev_ptr->key_size); 1199 dev_ptr->pm->parts->pscheme->get_part_info(dev_ptr->pm->parts, 1200 dev_ptr->pm_part, &info); 1201 pm_fmt_disk_line(m->mw, desc, dev_ptr->pm_name, 1202 info.size, NULL); 1203 } 1204 } 1205 1206 static void 1207 pm_cgd_edit_menufmt(menudesc *m, int opt, void *arg) 1208 { 1209 struct cgd_desc *dev_ptr = arg; 1210 switch (opt) { 1211 case PMC_MENU_DEV: 1212 wprintw(m->mw, "%-15s: %s", 1213 msg_string(MSG_cgd_dev_fmt), dev_ptr->pm_name); 1214 break; 1215 case PMC_MENU_ENCTYPE: 1216 wprintw(m->mw, "%-15s: %s", 1217 msg_string(MSG_cgd_enc_fmt), dev_ptr->enc_type); 1218 break; 1219 case PMC_MENU_KEYSIZE: 1220 wprintw(m->mw, "%-15s: %d", 1221 msg_string(MSG_cgd_key_fmt), dev_ptr->key_size); 1222 break; 1223 case PMC_MENU_IVTYPE: 1224 wprintw(m->mw, "%-15s: %s", 1225 msg_string(MSG_cgd_iv_fmt), dev_ptr->iv_type); 1226 break; 1227 case PMC_MENU_KEYGENTYPE: 1228 wprintw(m->mw, "%-15s: %s", 1229 msg_string(MSG_cgd_keygen_fmt), dev_ptr->keygen_type); 1230 break; 1231 case PMC_MENU_VERIFYTYPE: 1232 wprintw(m->mw, "%-15s: %s", 1233 msg_string(MSG_cgd_verif_fmt), dev_ptr->verify_type); 1234 break; 1235 } 1236 } 1237 1238 static int 1239 pm_cgd_set_value(menudesc *m, void *arg) 1240 { 1241 char *retstring; 1242 struct cgd_desc *dev_ptr = arg; 1243 1244 switch (m->cursel) { 1245 case PMC_MENU_DEV: 1246 pm_cgd_disk_set(dev_ptr, NULL); 1247 return 0; 1248 case PMC_MENU_ENCTYPE: 1249 process_menu(MENU_cgd_enctype, &retstring); 1250 dev_ptr->enc_type = retstring; 1251 if (! strcmp(retstring, "aes-xts")) 1252 dev_ptr->key_size = 256; 1253 if (! strcmp(retstring, "aes-cbc")) 1254 dev_ptr->key_size = 192; 1255 if (! strcmp(retstring, "blowfish-cbc")) 1256 dev_ptr->key_size = 128; 1257 if (! strcmp(retstring, "3des-cbc")) 1258 dev_ptr->key_size = 192; 1259 return 0; 1260 case PMC_MENU_KEYSIZE: 1261 if (! strcmp(dev_ptr->enc_type, "aes-xts")) 1262 dev_ptr->key_size += 1263 (dev_ptr->key_size < 512)? 256 : -256; 1264 if (! strcmp(dev_ptr->enc_type, "aes-cbc")) 1265 dev_ptr->key_size += 1266 (dev_ptr->key_size < 256)? 64 : -128; 1267 if (! strcmp(dev_ptr->enc_type, "blowfish-cbc")) 1268 dev_ptr->key_size = 128; 1269 if (! strcmp(dev_ptr->enc_type, "3des-cbc")) 1270 dev_ptr->key_size = 192; 1271 return 0; 1272 case PMC_MENU_IVTYPE: 1273 process_menu(MENU_cgd_ivtype, &retstring); 1274 dev_ptr->iv_type = retstring; 1275 return 0; 1276 case PMC_MENU_KEYGENTYPE: 1277 process_menu(MENU_cgd_keygentype, &retstring); 1278 dev_ptr->keygen_type = retstring; 1279 return 0; 1280 case PMC_MENU_VERIFYTYPE: 1281 process_menu(MENU_cgd_verifytype, &retstring); 1282 dev_ptr->verify_type = retstring; 1283 return 0; 1284 case PMC_MENU_REMOVE: 1285 dev_ptr->enabled = 0; 1286 return 0; 1287 } 1288 return -1; 1289 } 1290 1291 static void 1292 pm_cgd_init(void *arg1, void *arg2) 1293 { 1294 struct cgd_desc *dev_ptr = arg1; 1295 struct part_entry *disk_entrie = arg2; 1296 1297 memset(dev_ptr, 0, sizeof(*dev_ptr)); 1298 *dev_ptr = (struct cgd_desc) { 1299 .enabled = 1, 1300 .blocked = 0, 1301 .pm = NULL, 1302 .pm_name[0] = '\0', 1303 .pm_part = 0, 1304 .keygen_type = "pkcs5_pbkdf2/sha1", 1305 .verify_type = "disklabel", 1306 .enc_type = "aes-xts", 1307 .iv_type = "encblkno1", 1308 .key_size = 256, 1309 }; 1310 if (disk_entrie != NULL) { 1311 disk_entrie->parts->pscheme->get_part_device( 1312 disk_entrie->parts, disk_entrie->id, 1313 disk_entrie->fullname, sizeof(disk_entrie->fullname), 1314 NULL, logical_name, false); 1315 pm_cgd_disk_set(dev_ptr, disk_entrie); 1316 } 1317 } 1318 1319 static int 1320 pm_cgd_check(void *arg) 1321 { 1322 struct cgd_desc *dev_ptr = arg; 1323 1324 if (dev_ptr->blocked) 1325 return 0; 1326 if (dev_ptr->pm == NULL) 1327 dev_ptr->enabled = 0; 1328 else { 1329 pm_manage_getfreenode(&(dev_ptr->node), "cgd", &cgds_t_info); 1330 if (dev_ptr->node < 0) 1331 dev_ptr->enabled = 0; 1332 } 1333 return dev_ptr->enabled; 1334 } 1335 1336 static int 1337 pm_cgd_disk_set(struct cgd_desc *dev_ptr, struct part_entry *disk_entrie) 1338 { 1339 int alloc_disk_entrie = 0; 1340 1341 if (disk_entrie == NULL) { 1342 alloc_disk_entrie = 1; 1343 disk_entrie = malloc (sizeof(struct part_entry)); 1344 if (disk_entrie == NULL) 1345 return -2; 1346 *disk_entrie = pm_dev_list(PM_CGD); 1347 if (disk_entrie->retvalue < 0) { 1348 free(disk_entrie); 1349 return -1; 1350 } 1351 } 1352 dev_ptr->pm = disk_entrie->dev_ptr; 1353 dev_ptr->pm_part = disk_entrie->id; 1354 strlcpy(dev_ptr->pm_name, disk_entrie->fullname, SSTRSIZE); 1355 1356 if (alloc_disk_entrie) 1357 free(disk_entrie); 1358 return 0; 1359 } 1360 1361 int 1362 pm_cgd_edit(void *dev_ptr, struct part_entry *disk_entrie) 1363 { 1364 if (disk_entrie != NULL) 1365 dev_ptr = NULL; 1366 return pm_edit(PMC_MENU_END, pm_cgd_edit_menufmt, 1367 pm_cgd_set_value, pm_cgd_check, pm_cgd_init, 1368 disk_entrie, dev_ptr, 0, &cgds_t_info); 1369 } 1370 1371 static int 1372 pm_cgd_commit(void) 1373 { 1374 int i, error = 0; 1375 for (i = 0; i < MAX_CGD; i++) { 1376 if (! pm_cgd_check(&cgds[i])) 1377 continue; 1378 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 1379 "cgdconfig -g -i %s -k %s -o /tmp/cgd.%d.conf %s %d", 1380 cgds[i].iv_type, cgds[i].keygen_type, cgds[i].node, 1381 cgds[i].enc_type, cgds[i].key_size) != 0) { 1382 error++; 1383 continue; 1384 } 1385 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 1386 "cgdconfig -V re-enter cgd%d /dev/%s /tmp/cgd.%d.conf", 1387 cgds[i].node, cgds[i].pm_name, cgds[i].node) != 0) { 1388 error++; 1389 continue; 1390 } 1391 cgds[i].pm->blocked++; 1392 cgds[i].blocked = 1; 1393 } 1394 return error; 1395 } 1396 1397 /*** 1398 LVM 1399 ***/ 1400 1401 /* Add lvm logical volumes to pm list */ 1402 /* XXX: rewrite */ 1403 static void 1404 pm_lvm_find(void) 1405 { 1406 int i, ii, already_found; 1407 char dev[STRSIZE]; 1408 struct pm_devs *pm_i; 1409 1410 for (i = 0; i < MAX_LVM_VG; i++) { 1411 if (! lvms[i].blocked) 1412 continue; 1413 for (ii = 0; ii < MAX_LVM_LV; ii++) { 1414 if (! lvms[i].lv[ii].blocked || lvms[i].lv[ii].size < 1) 1415 continue; 1416 snprintf(dev, STRSIZE, "%s/%s", lvms[i].name, 1417 lvms[i].lv[ii].name); 1418 already_found = 0; 1419 SLIST_FOREACH(pm_i, &pm_head, l) 1420 if (!already_found && strcmp(pm_i->diskdev, 1421 dev) == 0) { 1422 pm_i->found = 1; 1423 already_found = 1; 1424 } 1425 if (already_found) 1426 /* We already added this device, skipping */ 1427 continue; 1428 pm_new->found = 1; 1429 pm_new->ptstart = 0; 1430 pm_new->ptsize = 0; 1431 pm_new->no_part = true; 1432 pm_new->refdev = &lvms[i].lv[ii]; 1433 pm_new->sectorsize = 1; 1434 pm_new->dlcylsize = MEG; 1435 strlcpy(pm_new->diskdev, dev, SSTRSIZE); 1436 strlcpy(pm_new->diskdev_descr, dev, STRSIZE); 1437 1438 if (SLIST_EMPTY(&pm_head)) 1439 SLIST_INSERT_HEAD(&pm_head, pm_new, l); 1440 else 1441 SLIST_INSERT_AFTER(pm_i, pm_new, l); 1442 pm_new = malloc(sizeof (struct pm_devs)); 1443 memset(pm_new, 0, sizeof *pm_new); 1444 } 1445 } 1446 } 1447 1448 static int 1449 pm_lvm_disk_add(menudesc *m, void *arg) 1450 { 1451 int i; 1452 lvms_t *dev_ptr = arg; 1453 struct part_entry disk_entrie = pm_dev_list(PM_LVM); 1454 if (disk_entrie.retvalue < 0) 1455 return disk_entrie.retvalue; 1456 1457 for (i = 0; i < MAX_LVM_PV; i++) 1458 if (dev_ptr->pv[i].pm == NULL) { 1459 dev_ptr->pv[i].pm = disk_entrie.dev_ptr; 1460 dev_ptr->pv[i].pm_part = disk_entrie.id; 1461 strlcpy(dev_ptr->pv[i].pm_name, disk_entrie.fullname, 1462 sizeof(dev_ptr->pv[i].pm_name)); 1463 break; 1464 } 1465 return 0; 1466 } 1467 1468 static int 1469 pm_lvm_disk_del(menudesc *m, void *arg) 1470 { 1471 int retvalue = -1, num_devs = 0; 1472 size_t i; 1473 int menu_no; 1474 lvms_t *dev_ptr = arg; 1475 menu_ent menu_entries[MAX_LVM_PV]; 1476 struct part_entry submenu_args[MAX_LVM_PV]; 1477 1478 for (i = 0; i < MAX_LVM_PV; i++) { 1479 if (dev_ptr->pv[i].pm == NULL) 1480 continue; 1481 menu_entries[num_devs] = (struct menu_ent) { 1482 .opt_name = dev_ptr->pv[i].pm_name, 1483 .opt_action = set_menu_select, 1484 .opt_flags = OPT_EXIT, 1485 }; 1486 submenu_args[num_devs].index = i; 1487 num_devs++; 1488 } 1489 1490 menu_no = new_menu(MSG_lvm_disks, 1491 menu_entries, num_devs, -1, -1, (num_devs+1<3)?3:num_devs+1, 13, 1492 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, NULL); 1493 if (menu_no == -1) 1494 return -1; 1495 process_menu(menu_no, &retvalue); 1496 free_menu(menu_no); 1497 1498 if (retvalue < 0 || retvalue >= num_devs) 1499 return -1; 1500 1501 dev_ptr->pv[submenu_args[retvalue].index].pm = NULL; 1502 1503 return 0; 1504 } 1505 1506 static void 1507 pm_lvm_menufmt(menudesc *m, int opt, void *arg) 1508 { 1509 int i, ok = 0; 1510 daddr_t used_size = 0; 1511 char buf1[STRSIZE]; buf1[0] = 0; 1512 char buf2[STRSIZE]; buf2[0] = 0; 1513 char devs[STRSIZE]; devs[0] = 0; 1514 lvms_t *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 1515 1516 if (dev_ptr->enabled == 0) 1517 return; 1518 snprintf(buf1, STRSIZE, "VG '%s'", dev_ptr->name); 1519 for (i = 0; i < MAX_LVM_PV; i++) 1520 if (dev_ptr->pv[i].pm != NULL) { 1521 strlcat(devs, dev_ptr->pv[i].pm_name, STRSIZE); 1522 strlcat(devs, " ", STRSIZE); 1523 ok = 1; 1524 } 1525 for (i = 0; i < MAX_LVM_LV; i++) 1526 used_size += dev_ptr->lv[i].size; 1527 if (ok) { 1528 snprintf(buf2, STRSIZE, "%" PRIi64 "/%" PRIi64, 1529 dev_ptr->total_size - used_size, dev_ptr->total_size); 1530 pm_fmt_disk_line(m->mw, buf1, devs, 0, buf2); 1531 } else { 1532 pm_fmt_disk_line(m->mw, buf1, NULL, 0, 1533 msg_string(MSG_lvm_err_menufmt)); 1534 } 1535 } 1536 1537 static void 1538 pm_lvm_edit_menufmt(menudesc *m, int opt, void *arg) 1539 { 1540 int i; 1541 char buf[STRSIZE]; 1542 lvms_t *dev_ptr = arg; 1543 strlcpy(buf, msg_string(MSG_auto), STRSIZE); 1544 1545 switch (opt) { 1546 case PML_MENU_PV: 1547 buf[0] = '\0'; 1548 for (i = 0; i < MAX_LVM_PV; i++) 1549 if (dev_ptr->pv[i].pm != NULL) 1550 snprintf(buf, STRSIZE, "%s %s", 1551 buf, dev_ptr->pv[i].pm_name); 1552 wprintw(m->mw, "%-20s: %s", 1553 msg_string(MSG_lvm_disks_fmt), buf); 1554 break; 1555 case PML_MENU_NAME: 1556 wprintw(m->mw, "%-20s: %s", 1557 msg_string(MSG_lvm_name_fmt), dev_ptr->name); 1558 break; 1559 case PML_MENU_MAXLOGICALVOLUMES: 1560 if (dev_ptr->maxlogicalvolumes > 0) 1561 snprintf(buf, STRSIZE, "%d", 1562 dev_ptr->maxlogicalvolumes); 1563 wprintw(m->mw, "%-20s: %s", 1564 msg_string(MSG_lvm_maxlv_fmt), buf); 1565 break; 1566 case PML_MENU_MAXPHYSICALVOLUMES: 1567 if (dev_ptr->maxphysicalvolumes > 0) 1568 snprintf(buf, STRSIZE, "%d", dev_ptr->maxphysicalvolumes); 1569 wprintw(m->mw, "%-20s: %s", 1570 msg_string(MSG_lvm_maxpv_fmt), buf); 1571 break; 1572 case PML_MENU_PHYSICALEXTENTSIZE: 1573 if (dev_ptr->physicalextentsize > 0) 1574 snprintf(buf, STRSIZE, "%dM", dev_ptr->physicalextentsize); 1575 wprintw(m->mw, "%-20s: %s", 1576 msg_string(MSG_lvm_extsiz_fmt), buf); 1577 break; 1578 } 1579 } 1580 1581 static int 1582 pm_lvm_set_value(menudesc *m, void *arg) 1583 { 1584 char buf[STRSIZE]; 1585 const char *msg_to_show = NULL; 1586 int *out_var = NULL; 1587 lvms_t *dev_ptr = arg; 1588 1589 static menu_ent menuent_disk_adddel[] = { 1590 { .opt_name=MSG_add, .opt_flags=OPT_EXIT, 1591 .opt_action=pm_lvm_disk_add }, 1592 { .opt_name=MSG_remove, .opt_flags=OPT_EXIT, 1593 .opt_action=pm_lvm_disk_del } 1594 }; 1595 static int menu_disk_adddel = -1; 1596 if (menu_disk_adddel == -1) { 1597 menu_disk_adddel = new_menu(NULL, menuent_disk_adddel, 1598 __arraycount(menuent_disk_adddel), 1599 -1, -1, 0, 10, MC_NOCLEAR, NULL, NULL, NULL, NULL, 1600 NULL); 1601 } 1602 1603 switch (m->cursel) { 1604 case PML_MENU_PV: 1605 process_menu(menu_disk_adddel, arg); 1606 return 0; 1607 case PML_MENU_NAME: 1608 msg_prompt_win(MSG_lvm_name_ask, -1, 18, 0, 0, 1609 dev_ptr->name, dev_ptr->name, SSTRSIZE); 1610 return 0; 1611 case PML_MENU_MAXLOGICALVOLUMES: 1612 msg_to_show = MSG_lvm_maxlv_ask; 1613 out_var = &(dev_ptr->maxlogicalvolumes); 1614 break; 1615 case PML_MENU_MAXPHYSICALVOLUMES: 1616 msg_to_show = MSG_lvm_maxpv_ask; 1617 out_var = &(dev_ptr->maxphysicalvolumes); 1618 break; 1619 case PML_MENU_PHYSICALEXTENTSIZE: 1620 msg_to_show = MSG_lvm_extsiz_ask; 1621 out_var = &(dev_ptr->physicalextentsize); 1622 break; 1623 case PML_MENU_REMOVE: 1624 dev_ptr->enabled = 0; 1625 return 0; 1626 } 1627 if (out_var == NULL || msg_to_show == NULL) 1628 return -1; 1629 snprintf(buf, SSTRSIZE, "%d", *out_var); 1630 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 1631 if (atoi(buf) >= 0) 1632 *out_var = atoi(buf); 1633 return 0; 1634 } 1635 1636 static void 1637 pm_lvm_init(void *arg, void* none) 1638 { 1639 lvms_t *dev_ptr = arg; 1640 1641 memset(dev_ptr, 0, sizeof *dev_ptr); 1642 *dev_ptr = (struct lvms_t) { 1643 .enabled = 1, 1644 .blocked = 0, 1645 .maxlogicalvolumes = MAX_LVM_PV, 1646 .maxphysicalvolumes = MAX_LVM_LV, 1647 .physicalextentsize = -1, 1648 }; 1649 sprintf(dev_ptr->name, "vg%.2d", rand()%100); 1650 } 1651 1652 static int 1653 pm_lvm_check(void *arg) 1654 { 1655 size_t i; 1656 bool ok = false; 1657 lvms_t *dev_ptr = arg; 1658 dev_ptr->total_size = 0; 1659 struct disk_part_info info; 1660 1661 for (i = 0; i < MAX_LVM_PV; i++) { 1662 if (dev_ptr->pv[i].pm != NULL) { 1663 if (!dev_ptr->pv[i].pm->parts->pscheme->get_part_info( 1664 dev_ptr->pv[i].pm->parts, dev_ptr->pv[i].pm_part, 1665 &info)) 1666 continue; 1667 ok = 1; 1668 dev_ptr->total_size += info.size; 1669 } 1670 } 1671 if (!ok) 1672 dev_ptr->enabled = 0; 1673 return dev_ptr->enabled; 1674 } 1675 1676 static void 1677 pm_lvmlv_menufmt(menudesc *m, int opt, void *arg) 1678 { 1679 char buf[STRSIZE]; 1680 lv_t *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 1681 1682 if (dev_ptr->size > 0) { 1683 snprintf(buf, STRSIZE, "'%s'", dev_ptr->name); 1684 pm_fmt_disk_line(m->mw, buf, NULL, dev_ptr->size, NULL); 1685 } 1686 } 1687 1688 static void 1689 pm_lvmlv_edit_menufmt(menudesc *m, int opt, void *arg) 1690 { 1691 1692 lv_t *dev_ptr = arg; 1693 char buf[STRSIZE]; 1694 strlcpy(buf, msg_string(MSG_auto), STRSIZE); 1695 1696 switch (opt) { 1697 case PMLV_MENU_NAME: 1698 wprintw(m->mw, "%-20s: %s", 1699 msg_string(MSG_lvmlv_name_fmt), dev_ptr->name); 1700 break; 1701 case PMLV_MENU_SIZE: 1702 wprintw(m->mw, "%-20s: %" PRIi64, 1703 msg_string(MSG_lvmlv_size_fmt), dev_ptr->size); 1704 break; 1705 case PMLV_MENU_READONLY: 1706 wprintw(m->mw, "%-20s: %s", 1707 msg_string(MSG_lvmlv_ro_fmt), 1708 dev_ptr->readonly? msg_string(MSG_Yes) : msg_string(MSG_No)); 1709 break; 1710 case PMLV_MENU_CONTIGUOUS: 1711 wprintw(m->mw, "%-20s: %s", 1712 msg_string(MSG_lvmlv_cont_fmt), 1713 dev_ptr->contiguous? msg_string(MSG_Yes) : msg_string(MSG_No)); 1714 break; 1715 case PMLV_MENU_EXTENTS: 1716 wprintw(m->mw, "%-20s: %s", 1717 msg_string(MSG_lvmlv_extnum_fmt), 1718 (strlen(dev_ptr->extents) > 0) ? 1719 dev_ptr->extents : msg_string(MSG_auto)); 1720 break; 1721 case PMLV_MENU_MINOR: 1722 if (dev_ptr->minor > 0) 1723 snprintf(buf, STRSIZE, "%dK", dev_ptr->minor); 1724 wprintw(m->mw, "%-20s: %s", 1725 msg_string(MSG_lvmlv_minor_fmt), buf); 1726 break; 1727 case PMLV_MENU_MIRRORS: 1728 wprintw(m->mw, "%-20s: %d", 1729 msg_string(MSG_lvmlv_mirrors_fmt), 1730 dev_ptr->mirrors); 1731 break; 1732 case PMLV_MENU_REGIONSIZE: 1733 if (dev_ptr->regionsize > 0) 1734 snprintf(buf, STRSIZE, "%dM", 1735 dev_ptr->regionsize); 1736 wprintw(m->mw, "%-20s: %s", 1737 msg_string(MSG_lvmlv_regsiz_fmt), buf); 1738 break; 1739 case PMLV_MENU_PERSISTENT: 1740 wprintw(m->mw, "%-20s: %s", 1741 msg_string(MSG_lvmlv_pers_fmt), 1742 dev_ptr->persistent ? 1743 msg_string(MSG_Yes) : msg_string(MSG_No)); 1744 break; 1745 case PMLV_MENU_READAHEAD: 1746 if (dev_ptr->readahead > 0) 1747 snprintf(buf, STRSIZE, "%d", 1748 dev_ptr->readahead); 1749 wprintw(m->mw, "%-20s: %s", 1750 msg_string(MSG_lvmlv_readahsect_fmt), buf); 1751 break; 1752 case PMLV_MENU_STRIPES: 1753 if (dev_ptr->stripes > 0) 1754 snprintf(buf, STRSIZE, "%d", dev_ptr->stripes); 1755 wprintw(m->mw, "%-20s: %s", 1756 msg_string(MSG_lvmlv_stripes_fmt), buf); 1757 break; 1758 case PMLV_MENU_STRIPESIZE: 1759 if (dev_ptr->stripesize > 0) 1760 snprintf(buf, STRSIZE, "%dK", dev_ptr->stripesize); 1761 wprintw(m->mw, "%-20s: %s", 1762 msg_string(MSG_lvmlv_stripesiz_fmt), buf); 1763 break; 1764 case PMLV_MENU_ZERO: 1765 wprintw(m->mw, "%-20s: %s", 1766 msg_string(MSG_lvmlv_zero_fmt), 1767 dev_ptr->zero ? 1768 msg_string(MSG_Yes) : msg_string(MSG_No)); 1769 break; 1770 } 1771 } 1772 1773 static int 1774 pm_lvmlv_set_value(menudesc *m, void *arg) 1775 { 1776 char buf[STRSIZE]; 1777 const char *msg_to_show = NULL; 1778 int *out_var = NULL; 1779 lv_t *dev_ptr = arg; 1780 1781 switch (m->cursel) { 1782 case PMLV_MENU_NAME: 1783 msg_prompt_win(MSG_lvmlv_name_ask, -1, 18, 0, 0, 1784 dev_ptr->name, dev_ptr->name, SSTRSIZE); 1785 return 0; 1786 case PMLV_MENU_SIZE: 1787 pm_edit_size_value(MSG_lvmlv_size_ask, 1788 pm->dlcylsize, &dev_ptr->size); /* XXX cylsize? */ 1789 break; 1790 case PMLV_MENU_READONLY: 1791 dev_ptr->readonly = !dev_ptr->readonly; 1792 return 0; 1793 case PMLV_MENU_CONTIGUOUS: 1794 dev_ptr->contiguous = !dev_ptr->contiguous; 1795 return 0; 1796 case PMLV_MENU_EXTENTS: 1797 msg_prompt_win(MSG_lvmlv_extnum_ask, -1, 18, 0, 0, 1798 dev_ptr->extents, dev_ptr->extents, SSTRSIZE); 1799 return 0; 1800 case PMLV_MENU_MINOR: 1801 msg_to_show = MSG_lvmlv_minor_ask; 1802 out_var = &(dev_ptr->minor); 1803 break; 1804 case PMLV_MENU_MIRRORS: 1805 msg_to_show = MSG_lvmlv_mirrors_ask; 1806 out_var = &(dev_ptr->mirrors); 1807 break; 1808 case PMLV_MENU_REGIONSIZE: 1809 msg_to_show = MSG_lvmlv_regsiz_ask; 1810 out_var = &(dev_ptr->regionsize); 1811 break; 1812 case PMLV_MENU_PERSISTENT: 1813 dev_ptr->persistent = !dev_ptr->persistent; 1814 return 0; 1815 case PMLV_MENU_READAHEAD: 1816 msg_to_show = MSG_lvmlv_readahsect_ask; 1817 out_var = &(dev_ptr->readahead); 1818 break; 1819 case PMLV_MENU_STRIPES: 1820 msg_to_show = MSG_lvmlv_stripes_ask; 1821 out_var = &(dev_ptr->stripes); 1822 break; 1823 case PMLV_MENU_STRIPESIZE: 1824 if (dev_ptr->stripesize << 1 > 512) 1825 dev_ptr->stripesize = 4; 1826 else 1827 dev_ptr->stripesize <<= 1; 1828 return 0; 1829 case PMLV_MENU_ZERO: 1830 dev_ptr->zero = !dev_ptr->zero; 1831 return 0; 1832 case PMLV_MENU_REMOVE: 1833 dev_ptr->size = 0; 1834 return 0; 1835 } 1836 if (out_var == NULL || msg_to_show == NULL) 1837 return -1; 1838 snprintf(buf, SSTRSIZE, "%d", *out_var); 1839 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 1840 if (atoi(buf) >= 0) 1841 *out_var = atoi(buf); 1842 return 0; 1843 } 1844 1845 static void 1846 pm_lvmlv_init(void *arg, void *none) 1847 { 1848 lv_t *dev_ptr = arg; 1849 memset(dev_ptr, 0, sizeof *(dev_ptr)); 1850 *dev_ptr = (struct lv_t) { 1851 .blocked = 0, 1852 .size = 1024, 1853 .stripesize = 64, 1854 }; 1855 sprintf (dev_ptr->name, "lvol%.2d", rand()%100); 1856 } 1857 1858 static int 1859 pm_lvmlv_check(void *arg) 1860 { 1861 lv_t *dev_ptr = arg; 1862 if (dev_ptr->size > 0 && strlen(dev_ptr->name) > 0) 1863 return 1; 1864 else { 1865 dev_ptr->size = 0; 1866 return 0; 1867 } 1868 } 1869 1870 static int 1871 pm_lvm_commit(void) 1872 { 1873 int i, ii, error; 1874 uint used_size = 0; 1875 char params[STRSIZE*3]; 1876 char devs[STRSIZE*3]; 1877 1878 for (i = 0; i < MAX_LVM_VG; i++) { 1879 /* Stage 0: checks */ 1880 if (! pm_lvm_check(&lvms[i])) 1881 continue; 1882 for (ii = 0; ii < MAX_LVM_LV; ii++) 1883 used_size += lvms[i].lv[ii].size; 1884 if (used_size > lvms[i].total_size) 1885 continue; 1886 1887 params[0] = '\0'; 1888 devs[0] = '\0'; 1889 error = 0; 1890 /* Stage 1: creating Physical Volumes (PV's) */ 1891 for (ii = 0; ii < MAX_LVM_PV && ! error; ii++) 1892 if (lvms[i].pv[ii].pm != NULL) { 1893 run_program(RUN_SILENT | RUN_ERROR_OK, 1894 "lvm pvremove -ffy /dev/r%s", 1895 (char*)lvms[i].pv[ii].pm_name); 1896 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 1897 "lvm pvcreate -ffy /dev/r%s", 1898 (char*)lvms[i].pv[ii].pm_name); 1899 if (error) 1900 break; 1901 snprintf(devs, STRSIZE*3, "%s /dev/r%s", devs, (char*)lvms[i].pv[ii].pm_name); 1902 } 1903 if (error) 1904 continue; 1905 /* Stage 2: creating Volume Groups (VG's) */ 1906 if (lvms[i].maxlogicalvolumes > 0) 1907 snprintf(params, STRSIZE*3, "%s -l %d", params, lvms[i].maxlogicalvolumes); 1908 if (lvms[i].maxphysicalvolumes > 0) 1909 snprintf(params, STRSIZE*3, "%s -p %d", params, lvms[i].maxphysicalvolumes); 1910 if (lvms[i].physicalextentsize > 0) 1911 snprintf(params, STRSIZE*3, "%s -s %d", params, lvms[i].physicalextentsize); 1912 error += run_program(RUN_DISPLAY | RUN_PROGRESS, "lvm vgcreate %s %s %s", 1913 params, lvms[i].name, devs); 1914 if (error) 1915 continue; 1916 /* Stage 3: creating Logical Volumes (LV's) */ 1917 for (ii = 0; ii < MAX_LVM_LV; ii++) { 1918 if (lvms[i].lv[ii].size <= 0) 1919 continue; 1920 1921 params[0] = '\0'; 1922 snprintf(params, STRSIZE*3, "%s -C %c", params, lvms[i].lv[ii].contiguous?'y':'n'); 1923 snprintf(params, STRSIZE*3, "%s -M %c", params, lvms[i].lv[ii].persistent?'y':'n'); 1924 snprintf(params, STRSIZE*3, "%s -p %s", params, lvms[i].lv[ii].readonly?"r":"rw"); 1925 snprintf(params, STRSIZE*3, "%s -Z %c", params, lvms[i].lv[ii].zero?'y':'n'); 1926 if (strlen(lvms[i].lv[ii].name) > 0) 1927 snprintf(params, STRSIZE*3, "%s -n %s", params, lvms[i].lv[ii].name); 1928 if (strlen(lvms[i].lv[ii].extents) > 0) 1929 snprintf(params, STRSIZE*3, "%s -l %s", params, lvms[i].lv[ii].extents); 1930 if (lvms[i].lv[ii].minor > 0) 1931 snprintf(params, STRSIZE*3, "%s --minor %d", params, lvms[i].lv[ii].minor); 1932 if (lvms[i].lv[ii].mirrors > 0) { 1933 snprintf(params, STRSIZE*3, "%s -m %d", params, lvms[i].lv[ii].mirrors); 1934 if (lvms[i].lv[ii].regionsize > 0) 1935 snprintf(params, STRSIZE*3, "%s -R %d", params, lvms[i].lv[ii].regionsize); 1936 } 1937 if (lvms[i].lv[ii].readahead > 0) 1938 snprintf(params, STRSIZE*3, "%s -r %d", params, lvms[i].lv[ii].readahead); 1939 if (lvms[i].lv[ii].stripes > 0) { 1940 snprintf(params, STRSIZE*3, "%s -i %d", params, lvms[i].lv[ii].stripes); 1941 if (lvms[i].lv[ii].stripesize > 0) 1942 snprintf(params, STRSIZE*3, "%s -I %d", params, lvms[i].lv[ii].stripesize); 1943 } 1944 snprintf(params, STRSIZE*3, "%s -L %" PRIi64 "M", 1945 params, lvms[i].lv[ii].size); 1946 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 1947 "lvm lvcreate %s %s", params, lvms[i].name); 1948 } 1949 if (! error) { 1950 lvms[i].blocked = 1; 1951 for (ii = 0; ii < MAX_LVM_PV; ii++) 1952 if (lvms[i].pv[ii].pm != NULL) 1953 lvms[i].pv[ii].pm->blocked++; 1954 for (ii = 0; ii < MAX_LVM_LV; ii++) 1955 if (lvms[i].lv[ii].size > 0) 1956 lvms[i].lv[ii].blocked = 1; 1957 } 1958 } 1959 1960 return 0; 1961 } 1962 1963 /*** 1964 Partman generic functions 1965 ***/ 1966 1967 int 1968 pm_getrefdev(struct pm_devs *pm_cur) 1969 { 1970 int i, ii, dev_num, num_devs, num_devs_s; 1971 char dev[SSTRSIZE]; dev[0] = '\0'; 1972 1973 pm_cur->refdev = NULL; 1974 if (! strncmp(pm_cur->diskdev, "cgd", 3)) { 1975 dev_num = pm_cur->diskdev[3] - '0'; 1976 for (i = 0; i < MAX_CGD; i++) 1977 if (cgds[i].blocked && cgds[i].node == dev_num) { 1978 pm_cur->refdev = &cgds[i]; 1979 snprintf(pm_cur->diskdev_descr, 1980 sizeof(pm_cur->diskdev_descr), 1981 "%s (%s, %s-%d)", 1982 pm_cur->diskdev_descr, cgds[i].pm_name, 1983 cgds[i].enc_type, cgds[i].key_size); 1984 break; 1985 } 1986 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) { 1987 dev_num = pm_cur->diskdev[3] - '0'; 1988 for (i = 0; i < MAX_VND; i++) 1989 if (vnds[i].blocked && vnds[i].node == dev_num) { 1990 pm_cur->refdev = &vnds[i]; 1991 vnds[i].pm->parts->pscheme->get_part_device( 1992 vnds[i].pm->parts, vnds[i].pm_part, 1993 dev, sizeof dev, NULL, plain_name, false); 1994 snprintf(pm_cur->diskdev_descr, 1995 sizeof(pm_cur->diskdev_descr), 1996 "%s (%s, %s)", 1997 pm_cur->diskdev_descr, dev, 1998 vnds[i].filepath); 1999 break; 2000 } 2001 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) { 2002 dev_num = pm_cur->diskdev[4] - '0'; 2003 for (i = 0; i < MAX_RAID; i++) 2004 if (raids[i].blocked && raids[i].node == dev_num) { 2005 pm_cur->refdev = &raids[i]; 2006 num_devs = 0; num_devs_s = 0; 2007 for (ii = 0; ii < MAX_IN_RAID; ii++) 2008 if (raids[i].comp[ii].parts != NULL) { 2009 if(raids[i].comp[ii].is_spare) 2010 num_devs_s++; 2011 else 2012 num_devs++; 2013 } 2014 snprintf(pm_cur->diskdev_descr, 2015 sizeof(pm_cur->diskdev_descr), 2016 "%s (lvl %d, %d disks, %d spare)", pm_cur->diskdev_descr, 2017 raids[i].raid_level, num_devs, num_devs_s); 2018 break; 2019 } 2020 } else 2021 return -1; 2022 return 0; 2023 } 2024 2025 /* Detect that partition is in use */ 2026 int 2027 pm_partusage(struct pm_devs *pm_cur, int part_num, int do_del) 2028 { 2029 int i, ii, retvalue = 0; 2030 struct disk_part_info info; 2031 part_id id; 2032 2033 if (part_num < 0) { 2034 /* Check all partitions on device */ 2035 for (id = 0; id < pm_cur->parts->num_part; id++) { 2036 if (!pm_cur->parts->pscheme->get_part_info( 2037 pm_cur->parts, id, &info)) 2038 continue; 2039 if (info.flags & (PTI_SEC_CONTAINER| 2040 PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL| 2041 PTI_RAW_PART)) 2042 continue; 2043 retvalue += pm_partusage(pm_cur, id, do_del); 2044 } 2045 return retvalue; 2046 } 2047 2048 id = (part_id)part_num; 2049 if (id >= pm_cur->parts->num_part) 2050 return 0; 2051 2052 for (i = 0; i < MAX_CGD; i++) 2053 if (cgds[i].enabled && 2054 cgds[i].pm == pm_cur && 2055 cgds[i].pm_part == id) { 2056 if (do_del) { 2057 cgds[i].pm = NULL; 2058 cgds[i].pm_name[0] = '\0'; 2059 } 2060 return 1; 2061 } 2062 for (i = 0; i < MAX_RAID; i++) 2063 for (ii = 0; ii < MAX_IN_RAID; ii++) 2064 if (raids[i].enabled && 2065 raids[i].comp[ii].parts == pm_cur->parts && 2066 raids[i].comp[ii].id == id) { 2067 if (do_del) 2068 raids[i].comp[ii].parts = NULL; 2069 return 1; 2070 } 2071 for (i = 0; i < MAX_LVM_VG; i++) 2072 for (ii = 0; ii < MAX_LVM_PV; ii++) 2073 if (lvms[i].enabled && 2074 lvms[i].pv[ii].pm == pm_cur && 2075 lvms[i].pv[ii].pm_part == id) { 2076 if (do_del) 2077 lvms[i].pv[ii].pm = NULL; 2078 return 1; 2079 } 2080 2081 return 0; 2082 } 2083 2084 static void 2085 pm_destroy_one(struct pm_devs *pm_i) 2086 { 2087 part_id i; 2088 2089 if (pm_i->parts != NULL) { 2090 if (pm_i->mounted != NULL) { 2091 for (i = 0; i < pm_i->parts->num_part; i++) 2092 free(pm_i->mounted[i]); 2093 } 2094 2095 pm_i->parts->pscheme->free(pm_i->parts); 2096 } 2097 free(pm_i); 2098 } 2099 2100 /* Clean up removed devices */ 2101 static int 2102 pm_clean(void) 2103 { 2104 int count = 0; 2105 struct pm_devs *pm_i, *tmp; 2106 2107 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp) 2108 if (! pm_i->found) { 2109 count++; 2110 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l); 2111 pm_destroy_one(pm_i); 2112 } 2113 return count; 2114 } 2115 2116 /* Free all pm storage */ 2117 void 2118 pm_destroy_all(void) 2119 { 2120 struct pm_devs *pm_i, *tmp; 2121 2122 if (pm_new != pm) 2123 pm_destroy_one(pm_new); 2124 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp) { 2125 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l); 2126 pm_destroy_one(pm_i); 2127 } 2128 } 2129 2130 void 2131 pm_setfstype(struct pm_devs *pm_cur, part_id id, int fstype, int fs_subtype) 2132 { 2133 struct disk_part_info info; 2134 2135 if (!pm_cur->parts->pscheme->get_part_info(pm_cur->parts, id, &info)) 2136 return; 2137 2138 info.nat_type = pm_cur->parts->pscheme->get_fs_part_type(fstype, fs_subtype); 2139 if (info.nat_type == NULL) 2140 return; 2141 info.fs_type = fstype; 2142 info.fs_sub_type = fs_subtype; 2143 pm_cur->parts->pscheme->set_part_info(pm_cur->parts, id, &info, NULL); 2144 } 2145 2146 static void 2147 pm_select(struct pm_devs *pm_devs_in) 2148 { 2149 pm = pm_devs_in; 2150 if (logfp) 2151 (void)fprintf(logfp, "Partman device: %s\n", pm->diskdev); 2152 } 2153 2154 void 2155 pm_rename(struct pm_devs *pm_cur) 2156 { 2157 #if 0 // XXX - convert to custom attribute or handle similar 2158 pm_select(pm_cur); 2159 msg_prompt_win(MSG_packname, -1, 18, 0, 0, pm_cur->bsddiskname, 2160 pm_cur->bsddiskname, sizeof pm_cur->bsddiskname); 2161 #ifndef NO_DISKLABEL 2162 (void) savenewlabel(pm_cur->bsdlabel, MAXPARTITIONS); 2163 #endif 2164 #endif 2165 } 2166 2167 int 2168 pm_editpart(int part_num) 2169 { 2170 //XXX partinfo backup = pm->bsdlabel[part_num]; 2171 2172 edit_ptn(&(struct menudesc){.cursel = part_num}, NULL); 2173 if (checkoverlap(pm->parts)) { 2174 hit_enter_to_continue(MSG_cantsave, NULL); 2175 //XXX pm->bsdlabel[part_num] = backup; 2176 return -1; 2177 } 2178 pm->unsaved = 1; 2179 return 0; 2180 } 2181 2182 /* Safe erase of disk */ 2183 int 2184 pm_shred(struct pm_devs *pm_cur, int part, int shredtype) 2185 { 2186 int error = -1; 2187 char dev[SSTRSIZE]; 2188 part_id id; 2189 2190 if (part < 0) 2191 return -1; 2192 2193 id = part; 2194 pm_cur->parts->pscheme->get_part_device(pm_cur->parts, id, dev, 2195 sizeof dev, NULL, plain_name, false); 2196 switch(shredtype) { 2197 case SHRED_ZEROS: 2198 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2199 "dd of=/dev/%s if=/dev/zero bs=1m progress=100 msgfmt=human", 2200 dev); 2201 break; 2202 case SHRED_RANDOM: 2203 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2204 "dd of=/dev/%s if=/dev/urandom bs=1m progress=100 msgfmt=human", 2205 dev); 2206 break; 2207 case SHRED_CRYPTO: 2208 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2209 "sh -c 'cgdconfig -s cgd0 /dev/%s aes-cbc 128 < /dev/urandom'", 2210 dev); /* XXX: cgd0?! */ 2211 if (! error) { 2212 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2213 "dd of=/dev/rcgd0d if=/dev/urandom bs=1m progress=100 msgfmt=human"); 2214 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2215 "cgdconfig -u cgd0"); 2216 } 2217 break; 2218 default: 2219 return -1; 2220 } 2221 pm_partusage(pm_cur, -1, 1); 2222 //XXX memset(&pm_cur->oldlabel, 0, sizeof pm_cur->oldlabel); 2223 //XXX memset(&pm_cur->bsdlabel, 0, sizeof pm_cur->bsdlabel); 2224 return error; 2225 } 2226 2227 #if 0 // XXX 2228 static int 2229 pm_mountall_sort(const void *a, const void *b) 2230 { 2231 return strcmp(mnts[*(const int *)a].on, mnts[*(const int *)b].on); 2232 } 2233 #endif 2234 2235 /* Mount all available partitions */ 2236 static int 2237 pm_mountall(void) 2238 { 2239 #if 0 // XXX 2240 int num_devs = 0; 2241 int mnts_order[MAX_MNTS]; 2242 int i, ii, error, ok; 2243 char dev[SSTRSIZE]; dev[0] = '\0'; 2244 struct pm_devs *pm_i; 2245 2246 localfs_dev[0] = '\0'; 2247 if (mnts == NULL) 2248 mnts = calloc(MAX_MNTS, sizeof(*mnts)); 2249 2250 SLIST_FOREACH(pm_i, &pm_head, l) { 2251 ok = 0; 2252 for (i = 0; i < MAXPARTITIONS; i++) { 2253 if (!(pm_i->bsdlabel[i].pi_flags & PIF_MOUNT && 2254 pm_i->bsdlabel[i].mnt_opts != NULL)) 2255 continue; 2256 mnts[num_devs].mnt_opts = pm_i->bsdlabel[i].mnt_opts; 2257 if (strlen(pm_i->bsdlabel[i].mounted) > 0) { 2258 /* Device is already mounted. So, doing mount_null */ 2259 strlcpy(mnts[num_devs].dev, pm_i->bsdlabel[i].mounted, MOUNTLEN); 2260 mnts[num_devs].mnt_opts = "-t null"; 2261 } else { 2262 pm_getdevstring(dev, SSTRSIZE, pm_i, i); 2263 snprintf(mnts[num_devs].dev, STRSIZE, "/dev/%s", dev); 2264 } 2265 mnts[num_devs].on = pm_i->bsdlabel[i].pi_mount; 2266 if (strcmp(pm_i->bsdlabel[i].pi_mount, "/") == 0) { 2267 if (pm_i->no_part) 2268 pm_i->bootable = 1; 2269 /* Use disk with / as a default if the user has 2270 the sets on a local disk */ 2271 strlcpy(localfs_dev, pm_i->diskdev, SSTRSIZE); 2272 } 2273 num_devs++; 2274 ok = 1; 2275 } 2276 if (ok) 2277 md_pre_mount(NULL, 0); 2278 } 2279 if (strlen(localfs_dev) < 1) { 2280 hit_enter_to_continue(MSG_noroot, NULL); 2281 return -1; 2282 } 2283 for (i = 0; i < num_devs; i++) 2284 mnts_order[i] = i; 2285 qsort(mnts_order, num_devs, sizeof mnts_order[0], pm_mountall_sort); 2286 2287 for (i = 0; i < num_devs; i++) { 2288 ii = mnts_order[i]; 2289 make_target_dir(mnts[ii].on); 2290 error = target_mount_do(mnts[ii].mnt_opts, mnts[ii].dev, mnts[ii].on); 2291 if (error) 2292 return error; 2293 } 2294 #endif 2295 return 0; 2296 } 2297 2298 /* Mount partition bypassing ordinary order */ 2299 static int 2300 pm_mount(struct pm_devs *pm_cur, int part_num) 2301 { 2302 int error = 0; 2303 #if 0 // XXX 2304 char buf[MOUNTLEN]; 2305 2306 if (strlen(pm_cur->bsdlabel[part_num].mounted) > 0) 2307 return 0; 2308 2309 snprintf(buf, sizeof(buf), "/tmp/%s%c", pm_cur->diskdev, 2310 part_num + 'a'); 2311 if (! dir_exists_p(buf)) 2312 run_program(RUN_DISPLAY | RUN_PROGRESS, "/bin/mkdir -p %s", buf); 2313 if (pm_cur->bsdlabel[part_num].pi_flags & PIF_MOUNT && 2314 pm_cur->bsdlabel[part_num].mnt_opts != NULL && 2315 strlen(pm_cur->bsdlabel[part_num].mounted) < 1) 2316 error += run_program(RUN_DISPLAY | RUN_PROGRESS, "/sbin/mount %s /dev/%s%c %s", 2317 pm_cur->bsdlabel[part_num].mnt_opts, 2318 pm_cur->diskdev, part_num + 'a', buf); 2319 2320 if (error) 2321 pm_cur->bsdlabel[part_num].mounted[0] = '\0'; 2322 else { 2323 strlcpy(pm_cur->bsdlabel[part_num].mounted, buf, MOUNTLEN); 2324 pm_cur->blocked++; 2325 } 2326 #endif 2327 return error; 2328 } 2329 2330 void 2331 pm_umount(struct pm_devs *pm_cur, int part_num) 2332 { 2333 char buf[SSTRSIZE]; buf[0] = '\0'; 2334 part_id id; 2335 2336 if (part_num < 0) 2337 return; 2338 id = (part_id)part_num; 2339 2340 pm_cur->parts->pscheme->get_part_device(pm_cur->parts, id, buf, 2341 sizeof buf, NULL, plain_name, false); 2342 2343 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 2344 "umount -f /dev/%s", buf) == 0) { 2345 free(pm_cur->mounted[id]); 2346 pm_cur->mounted[id] = NULL; 2347 if (pm_cur->blocked > 0) 2348 pm_cur->blocked--; 2349 } 2350 } 2351 2352 int 2353 pm_unconfigure(struct pm_devs *pm_cur) 2354 { 2355 int error = 0; 2356 if (! strncmp(pm_cur->diskdev, "cgd", 3)) { 2357 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "cgdconfig -u %s", pm_cur->diskdev); 2358 if (! error && pm_cur->refdev != NULL) { 2359 ((struct cgd_desc*)pm_cur->refdev)->pm->blocked--; 2360 ((struct cgd_desc*)pm_cur->refdev)->blocked = 0; 2361 } 2362 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) { 2363 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "vndconfig -u %s", pm_cur->diskdev); 2364 if (! error && pm_cur->refdev != NULL) { 2365 ((struct vnd_desc*)pm_cur->refdev)->pm->blocked--; 2366 ((struct vnd_desc*)pm_cur->refdev)->blocked = 0; 2367 } 2368 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) { 2369 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "raidctl -u %s", pm_cur->diskdev); 2370 if (! error && pm_cur->refdev != NULL) { 2371 ((struct raid_desc*)pm_cur->refdev)->blocked = 0; 2372 #if 0 // XXX 2373 for (i = 0; i < MAX_IN_RAID; i++) 2374 if (((struct raid_desc*)pm_cur->refdev)->comp[i].parts != NULL) 2375 ((raids_t*)pm_cur->refdev)->pm[i]->blocked--; 2376 #endif 2377 } 2378 } else if (! strncmp(pm_cur->diskdev, "dk", 2)) { 2379 if (pm_cur->refdev == NULL) 2380 return -2; 2381 /* error = */ 2382 run_program(RUN_DISPLAY | RUN_PROGRESS, "dkctl %s delwedge %s", 2383 ((struct pm_devs*)pm_cur->refdev)->diskdev, pm_cur->diskdev); 2384 #if 0 // XXX 2385 if (! error) { 2386 if (pm_cur->refdev != NULL && ((struct pm_devs*)pm_cur->refdev)->blocked > 0) 2387 ((struct pm_devs*)pm_cur->refdev)->blocked--; 2388 sscanf(pm_cur->diskdev, "dk%d", &num); 2389 if (num >= 0 && num < MAX_WEDGES) 2390 wedges[num].allocated = 0; 2391 } 2392 #endif 2393 } /* XXX: lvm */ 2394 else 2395 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "eject -t disk /dev/%sd", 2396 pm_cur->diskdev); 2397 if (!error) 2398 pm_cur->found = 0; 2399 return error; 2400 } 2401 2402 /* Last checks before leaving partition manager */ 2403 static int 2404 pm_lastcheck(void) 2405 { 2406 FILE *file_tmp = fopen(concat_paths(targetroot_mnt, "/etc/fstab"), "r"); 2407 if (file_tmp == NULL) 2408 return 1; 2409 fclose(file_tmp); 2410 return 0; 2411 } 2412 2413 /* Are there unsaved changes? */ 2414 static int 2415 pm_needsave(void) 2416 { 2417 struct pm_devs *pm_i; 2418 SLIST_FOREACH(pm_i, &pm_head, l) 2419 if (pm_i->unsaved) { 2420 /* Oops, we have unsaved changes */ 2421 changed = 1; 2422 msg_display(MSG_saveprompt); 2423 return ask_yesno(NULL); 2424 } 2425 return 0; 2426 } 2427 2428 /* Write all changes to disk */ 2429 static int 2430 pm_commit(menudesc *m, void *arg) 2431 { 2432 int retcode; 2433 struct pm_devs *pm_i; 2434 struct install_partition_desc install; 2435 2436 if (m != NULL && arg != NULL) 2437 ((struct part_entry *)arg)[0].retvalue = m->cursel + 1; 2438 2439 SLIST_FOREACH(pm_i, &pm_head, l) { 2440 if (! pm_i->unsaved) 2441 continue; 2442 pm_select(pm_i); 2443 install_desc_from_parts(&install, pm_i->parts); 2444 2445 if (pm_i->no_part) { 2446 if (make_filesystems(&install) != 0) { 2447 if (logfp) 2448 fprintf(logfp, "Special disk %s preparing error\n", pm_i->diskdev); 2449 goto next; 2450 } 2451 pm_i->unsaved = 0; 2452 } else if (pm_i->parts != NULL) { 2453 2454 if (!pm_i->parts->pscheme->write_to_disk(pm_i->parts) || 2455 set_swap_if_low_ram(NULL) != 0 || 2456 md_post_disklabel(&install, pm_i->parts) != 0 || /* Enable swap and check badblock */ 2457 make_filesystems(&install) != 0 /* Create filesystems with newfs */ 2458 ) { 2459 /* Oops, something failed... */ 2460 if (logfp) 2461 fprintf(logfp, "Disk %s preparing error\n", pm_i->diskdev); 2462 goto next; 2463 } 2464 pm_i->unsaved = 0; 2465 } 2466 next: 2467 free_install_desc(&install); 2468 } 2469 2470 /* Call all functions that may create new devices */ 2471 if ((retcode = pm_raid_commit()) != 0) { 2472 if (logfp) 2473 fprintf(logfp, "RAIDframe configuring error #%d\n", retcode); 2474 return -1; 2475 } 2476 if ((retcode = pm_cgd_commit()) != 0) { 2477 if (logfp) 2478 fprintf(logfp, "CGD configuring error #%d\n", retcode); 2479 return -1; 2480 } 2481 if ((retcode = pm_lvm_commit()) != 0) { 2482 if (logfp) 2483 fprintf(logfp, "LVM configuring error #%d\n", retcode); 2484 return -1; 2485 } 2486 if ((retcode = pm_vnd_commit()) != 0) { 2487 if (logfp) 2488 fprintf(logfp, "VND configuring error #%d\n", retcode); 2489 return -1; 2490 } 2491 if (m != NULL && arg != NULL) 2492 pm_upddevlist(m, arg); 2493 if (logfp) 2494 fflush (logfp); 2495 return 0; 2496 } 2497 2498 static int 2499 pm_savebootsector(void) 2500 { 2501 #if 0 // XXX 2502 struct pm_devs *pm_i; 2503 SLIST_FOREACH(pm_i, &pm_head, l) 2504 if (pm_i->bootable) { 2505 if (! strncmp("raid", pm_i->diskdev, 4)) 2506 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 2507 "raidctl -v -A root %s", pm_i->diskdev) != 0) { 2508 if (logfp) 2509 fprintf(logfp, "Error writting RAID bootsector to %s\n", 2510 pm_i->diskdev); 2511 continue; 2512 } 2513 if (pm_i->no_part) { 2514 if (pm_i->rootpart < 0 || 2515 run_program(RUN_DISPLAY | RUN_PROGRESS, 2516 "gpt biosboot -i %d %s", 2517 pm_i->rootpart + 1, pm_i->diskdev) != 0) { 2518 if (logfp) 2519 fprintf(logfp, "Error writting GPT bootsector to %s\n", 2520 pm_i->diskdev); 2521 continue; 2522 } 2523 } else { 2524 pm_select(pm_i); 2525 if ( 2526 #ifndef NO_DISKLABEL 2527 !check_partitions(pm_i, pm_i->parts) || 2528 #endif 2529 md_post_newfs() != 0) { 2530 if (logfp) 2531 fprintf(logfp, "Error writting bootsector to %s\n", 2532 pm_i->diskdev); 2533 continue; 2534 } 2535 } 2536 } 2537 #endif 2538 return 0; 2539 } 2540 2541 /* Function for 'Enter'-menu */ 2542 static int 2543 pm_submenu(menudesc *m, void *arg) 2544 { 2545 int part_num = -1; 2546 struct pm_devs *pm_cur = NULL; 2547 ((struct part_entry *)arg)[0].retvalue = m->cursel + 1; 2548 2549 switch (((struct part_entry *)arg)[m->cursel].type) { 2550 case PM_DISK: 2551 case PM_PART: 2552 case PM_SPEC: 2553 if (((struct part_entry *)arg)[m->cursel].dev_ptr != NULL) { 2554 pm_cur = ((struct part_entry *)arg)[m->cursel].dev_ptr; 2555 if (pm_cur == NULL) 2556 return -1; 2557 if (pm_cur->blocked) { 2558 msg_display(MSG_wannaunblock); 2559 if (!ask_noyes(NULL)) 2560 return -2; 2561 pm_cur->blocked = 0; 2562 } 2563 pm_select(pm_cur); 2564 } 2565 default: 2566 break; 2567 } 2568 2569 switch (((struct part_entry *)arg)[m->cursel].type) { 2570 case PM_DISK: 2571 if (pm_cur != NULL 2572 && pm_cur->parts == NULL) { 2573 2574 #ifndef NO_DISKLABEL 2575 struct install_partition_desc install = { 0 }; 2576 #endif 2577 const struct disk_partitioning_scheme *ps = 2578 select_part_scheme(pm_cur, NULL, false, 2579 NULL); 2580 if (!ps) 2581 return 0; 2582 2583 struct disk_partitions *parts = 2584 (*ps->create_new_for_disk)(pm_cur->diskdev, 2585 0, pm_cur->dlsize, pm_cur->dlsize, false); 2586 if (!parts) 2587 return 0; 2588 2589 pm_cur->parts = parts; 2590 if (pm->dlsize > ps->size_limit) 2591 pm->dlsize = ps->size_limit; 2592 2593 if (pm_cur->parts == NULL) 2594 break; 2595 wclear(stdscr); 2596 wrefresh(stdscr); 2597 #ifndef NO_DISKLABEL 2598 install_desc_from_parts(&install, pm->parts); 2599 make_bsd_partitions(&install); 2600 free_install_desc(&install); 2601 #endif 2602 } 2603 // XXX 2604 // if (pm_cur != NULL 2605 // && pm_cur->label_type == PM_LABEL_GPT) { 2606 // process_menu(MENU_pmgptentry, &part_num); 2607 // pm_wedges_fill(pm_cur); 2608 // } else { 2609 process_menu(MENU_pmdiskentry, &part_num); 2610 // } 2611 break; 2612 case PM_PART: 2613 part_num = ((struct part_entry *)arg)[m->cursel].id; 2614 process_menu(MENU_pmpartentry, &part_num); 2615 // if (pm_cur != NULL && pm_cur->label_type == PM_LABEL_GPT) 2616 // pm_wedges_fill(pm_cur); 2617 break; 2618 case PM_SPEC: 2619 part_num = 0; 2620 process_menu(MENU_pmpartentry, &part_num); 2621 break; 2622 case PM_RAID: 2623 return pm_edit(PMR_MENU_END, pm_raid_edit_menufmt, 2624 pm_raid_set_value, pm_raid_check, pm_raid_init, 2625 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 0, &raids_t_info); 2626 case PM_VND: 2627 return pm_edit(PMV_MENU_END, pm_vnd_edit_menufmt, 2628 pm_vnd_set_value, pm_vnd_check, pm_vnd_init, 2629 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 0, &vnds_t_info); 2630 case PM_CGD: 2631 return pm_cgd_edit(((struct part_entry *)arg)[m->cursel].dev_ptr, 2632 NULL); 2633 case PM_LVM: 2634 return pm_edit(PML_MENU_END, pm_lvm_edit_menufmt, 2635 pm_lvm_set_value, pm_lvm_check, pm_lvm_init, 2636 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 0, &lvms_t_info); 2637 case PM_LVMLV: 2638 return pm_edit(PMLV_MENU_END, pm_lvmlv_edit_menufmt, 2639 pm_lvmlv_set_value, pm_lvmlv_check, pm_lvmlv_init, 2640 NULL, ((struct part_entry *)arg)[m->cursel].dev_ptr, 2641 ((struct part_entry *)arg)[m->cursel].dev_ptr_delta, &lv_t_info); 2642 } 2643 return 0; 2644 } 2645 2646 /* Functions that generate menu entries text */ 2647 static void 2648 pm_menufmt(menudesc *m, int opt, void *arg) 2649 { 2650 const char *dev_status = ""; 2651 char buf[STRSIZE], dev[STRSIZE]; 2652 part_id part_num = ((struct part_entry *)arg)[opt].id; 2653 struct pm_devs *pm_cur = ((struct part_entry *)arg)[opt].dev_ptr; 2654 struct disk_partitions *parts = ((struct part_entry *)arg)[opt].parts; 2655 struct disk_part_info info; 2656 const char *mount_point, *fstype; 2657 2658 switch (((struct part_entry *)arg)[opt].type) { 2659 case PM_DISK: 2660 if (pm_cur->blocked) 2661 dev_status = msg_string(MSG_pmblocked); 2662 else if (! pm_cur->unsaved) 2663 dev_status = msg_string(MSG_pmunchanged); 2664 else if (pm_cur->bootable) 2665 dev_status = msg_string(MSG_pmsetboot); 2666 else 2667 dev_status = msg_string(MSG_pmused); 2668 wprintw(m->mw, "%-33.32s %33.32s", 2669 pm_cur->diskdev_descr, 2670 dev_status); 2671 break; 2672 case PM_PART: 2673 if (parts->pscheme->get_part_device != NULL) 2674 parts->pscheme->get_part_device( 2675 parts, part_num, 2676 dev, sizeof dev, NULL, plain_name, false); 2677 else 2678 strcpy(dev, "-"); 2679 parts->pscheme->get_part_info(parts, 2680 part_num, &info); 2681 if (pm_cur->mounted != NULL && 2682 pm_cur->mounted[part_num] != NULL && 2683 pm_cur->mounted[part_num][0] != 0) 2684 mount_point = msg_string(MSG_pmmounted); 2685 else 2686 mount_point = msg_string(MSG_pmunused); 2687 fstype = getfslabelname(info.fs_type, 2688 info.fs_sub_type); 2689 if (info.last_mounted != NULL) { 2690 snprintf(buf, STRSIZE, "%s (%s) %s", 2691 info.last_mounted, fstype, 2692 mount_point); 2693 pm_fmt_disk_line(m->mw, dev, buf, 2694 info.size, NULL); 2695 } else { 2696 if (fstype != NULL) { 2697 strlcat(dev, " (", sizeof(dev)); 2698 strlcat(dev, fstype, sizeof(dev)); 2699 strlcat(dev, ")", sizeof(dev)); 2700 } 2701 pm_fmt_disk_line(m->mw, dev, NULL, 2702 info.size, NULL); 2703 } 2704 break; 2705 case PM_SPEC: 2706 /* XXX ? */ 2707 pm_fmt_disk_line(m->mw, pm_cur->diskdev_descr, NULL, 2708 pm_cur->dlsize, NULL); 2709 break; 2710 case PM_RAID: 2711 pm_raid_menufmt(m, opt, arg); 2712 break; 2713 case PM_VND: 2714 pm_vnd_menufmt(m, opt, arg); 2715 break; 2716 case PM_CGD: 2717 pm_cgd_menufmt(m, opt, arg); 2718 break; 2719 case PM_LVM: 2720 pm_lvm_menufmt(m, opt, arg); 2721 break; 2722 case PM_LVMLV: 2723 pm_lvmlv_menufmt(m, opt, arg); 2724 break; 2725 } 2726 } 2727 2728 /* Submenu for RAID/LVM/CGD/VND */ 2729 static void 2730 pm_upddevlist_adv(menudesc *m, void *arg, int *i, 2731 pm_upddevlist_adv_t *d) 2732 { 2733 int ii; 2734 if (d->create_msg != NULL) { 2735 /* We want to have menu entry that creates a new device */ 2736 ((struct part_entry *)arg)[*i].type = d->pe_type; 2737 ((struct part_entry *)arg)[*i].dev_ptr = NULL; 2738 ((struct part_entry *)arg)[*i].dev_ptr_delta = d->s->parent_size * d->sub_num; 2739 m->opts[(*i)++] = (struct menu_ent) { 2740 .opt_name = d->create_msg, 2741 .opt_action = pm_submenu, 2742 }; 2743 } 2744 for (ii = 0; ii < d->s->max; ii++) { 2745 if (d->s->entry_enabled == NULL || 2746 d->s->entry_blocked == NULL || 2747 *(int*)((char*)d->s->entry_enabled + d->s->entry_size * ii + 2748 d->s->parent_size * d->sub_num) == 0 || 2749 *(int*)((char*)d->s->entry_blocked + d->s->entry_size * ii + 2750 d->s->parent_size * d->sub_num) != 0) 2751 continue; 2752 /* We have a entry for displaying */ 2753 changed = 1; 2754 m->opts[*i] = (struct menu_ent) { 2755 .opt_name = NULL, 2756 .opt_action = pm_submenu, 2757 }; 2758 ((struct part_entry *)arg)[*i].type = d->pe_type; 2759 ((struct part_entry *)arg)[*i].dev_ptr = (char*)d->s->entry_first + 2760 d->s->entry_size * ii + d->s->parent_size * d->sub_num; 2761 (*i)++; 2762 /* We should show submenu for current entry */ 2763 if (d->sub != NULL) { 2764 d->sub->sub_num = ii; 2765 pm_upddevlist_adv(m, arg, i, d->sub); 2766 } 2767 } 2768 } 2769 2770 /* Update partman main menu with devices list */ 2771 static int 2772 pm_upddevlist(menudesc *m, void *arg) 2773 { 2774 int i = 0; 2775 size_t ii; 2776 struct pm_devs *pm_i; 2777 struct disk_partitions *secondary; 2778 const struct disk_partitioning_scheme *ps; 2779 struct disk_part_info info; 2780 2781 if (arg != NULL) 2782 ((struct part_entry *)arg)[0].retvalue = m->cursel + 1; 2783 2784 changed = 0; 2785 /* Mark all devices as not found */ 2786 SLIST_FOREACH(pm_i, &pm_head, l) { 2787 if (pm_i->parts != NULL) { 2788 pm_i->parts->pscheme->free(pm_i->parts); 2789 pm_i->parts = NULL; 2790 } 2791 if (pm_i->found > 0) 2792 pm_i->found = 0; 2793 } 2794 2795 /* Detect all present devices */ 2796 (void)find_disks("partman", false); 2797 if (have_lvm) 2798 pm_lvm_find(); 2799 pm_clean(); 2800 2801 if (m == NULL || arg == NULL) 2802 return -1; 2803 2804 SLIST_FOREACH(pm_i, &pm_head, l) { 2805 m->opts[i].opt_name = NULL; 2806 m->opts[i].opt_exp_name = NULL; 2807 m->opts[i].opt_action = pm_submenu; 2808 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 2809 ((struct part_entry *)arg)[i].id = NO_PART; 2810 if (pm_i->no_part) 2811 ((struct part_entry *)arg)[i].type = PM_SPEC; 2812 else { 2813 ps = pm_i->parts != NULL ? pm_i->parts->pscheme : NULL; 2814 secondary = NULL; 2815 2816 ((struct part_entry *)arg)[i].type = PM_DISK; 2817 2818 for (ii = 0; pm_i->parts != NULL && 2819 ii < pm_i->parts->num_part; ii++) { 2820 if (!ps->get_part_info( 2821 pm_i->parts, ii, &info)) 2822 continue; 2823 if (info.flags & PTI_SEC_CONTAINER) { 2824 if (secondary == NULL && 2825 ps->secondary_scheme != NULL) 2826 secondary = ps-> 2827 secondary_partitions( 2828 pm_i->parts, 2829 info.start, false); 2830 continue; 2831 } 2832 if (info.flags & (PTI_WHOLE_DISK| 2833 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 2834 continue; 2835 if (info.fs_type == FS_UNUSED) 2836 continue; 2837 if (i >= MAX_ENTRIES) 2838 break; 2839 i++; 2840 m->opts[i].opt_name = NULL; 2841 m->opts[i].opt_exp_name = NULL; 2842 m->opts[i].opt_action = pm_submenu; 2843 ((struct part_entry *)arg)[i].parts = 2844 pm_i->parts; 2845 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 2846 ((struct part_entry *)arg)[i].id = ii; 2847 ((struct part_entry *)arg)[i].type = PM_PART; 2848 } 2849 2850 for (ii = 0; secondary != NULL && 2851 ii < secondary->num_part; ii++) { 2852 if (!secondary->pscheme->get_part_info( 2853 secondary, ii, &info)) 2854 continue; 2855 if (info.flags & (PTI_WHOLE_DISK| 2856 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 2857 continue; 2858 if (info.fs_type == FS_UNUSED) 2859 continue; 2860 if (i >= MAX_ENTRIES) 2861 break; 2862 i++; 2863 m->opts[i].opt_name = NULL; 2864 m->opts[i].opt_exp_name = NULL; 2865 m->opts[i].opt_action = pm_submenu; 2866 ((struct part_entry *)arg)[i].parts = secondary; 2867 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 2868 ((struct part_entry *)arg)[i].id = ii; 2869 ((struct part_entry *)arg)[i].type = PM_PART; 2870 } 2871 } 2872 i++; 2873 } 2874 if (have_cgd) { 2875 pm_upddevlist_adv(m, arg, &i, 2876 &(pm_upddevlist_adv_t) {MSG_create_cgd, PM_CGD, &cgds_t_info, 0, NULL}); 2877 } 2878 if (have_lvm) { 2879 pm_upddevlist_adv(m, arg, &i, 2880 &(pm_upddevlist_adv_t) {MSG_create_cnd, PM_VND, &vnds_t_info, 0, NULL}); 2881 pm_upddevlist_adv(m, arg, &i, 2882 &(pm_upddevlist_adv_t) {MSG_create_vg, PM_LVM, &lvms_t_info, 0, 2883 &(pm_upddevlist_adv_t) {MSG_create_lv, PM_LVMLV, &lv_t_info, 0, NULL}}); 2884 } 2885 if (have_raid) { 2886 pm_upddevlist_adv(m, arg, &i, 2887 &(pm_upddevlist_adv_t) {MSG_create_raid, PM_RAID, &raids_t_info, 0, NULL}); 2888 } 2889 2890 m->opts[i++] = (struct menu_ent) { 2891 .opt_name = MSG_updpmlist, 2892 .opt_action = pm_upddevlist, 2893 }; 2894 m->opts[i ] = (struct menu_ent) { 2895 .opt_name = MSG_savepm, 2896 .opt_action = pm_commit, 2897 }; 2898 for (ii = 0; ii <= (size_t)i; ii++) { 2899 m->opts[ii].opt_flags = OPT_EXIT; 2900 } 2901 2902 if (((struct part_entry *)arg)[0].retvalue >= 0) 2903 m->cursel = ((struct part_entry *)arg)[0].retvalue - 1; 2904 return i; 2905 } 2906 2907 static void 2908 pm_menuin(menudesc *m, void *arg) 2909 { 2910 if (cursel > m->numopts) 2911 m->cursel = m->numopts; 2912 else if (cursel < 0) 2913 m->cursel = 0; 2914 else 2915 m->cursel = cursel; 2916 } 2917 2918 static void 2919 pm_menuout(menudesc *m, void *arg) 2920 { 2921 cursel = m->cursel; 2922 } 2923 2924 /* Main partman function */ 2925 int 2926 partman(void) 2927 { 2928 int menu_no, menu_num_entries; 2929 static int firstrun = 1; 2930 menu_ent menu_entries[MAX_ENTRIES+6]; 2931 struct part_entry args[MAX_ENTRIES]; 2932 2933 if (firstrun) { 2934 check_available_binaries(); 2935 2936 if (!have_raid) 2937 remove_raid_options(); 2938 else if (!(raids = calloc(MAX_RAID, sizeof(*raids)))) 2939 have_raid = 0; 2940 2941 #define remove_vnd_options() (void)0 2942 if (!have_vnd) 2943 remove_vnd_options(); 2944 else if (!(vnds = calloc(MAX_VND, sizeof(*vnds)))) 2945 have_vnd = 0; 2946 2947 if (!have_cgd) 2948 remove_cgd_options(); 2949 else if (!(cgds = calloc(MAX_CGD, sizeof(*cgds)))) 2950 have_cgd = 0; 2951 2952 if (!have_lvm) 2953 remove_lvm_options(); 2954 else if (!(lvms = calloc(MAX_LVM_VG, sizeof(*lvms)))) 2955 have_lvm = 0; 2956 2957 if (!have_gpt) 2958 remove_gpt_options(); 2959 2960 raids_t_info = (structinfo_t) { 2961 .max = MAX_RAID, 2962 .entry_size = sizeof raids[0], 2963 .entry_first = &raids[0], 2964 .entry_enabled = &(raids[0].enabled), 2965 .entry_blocked = &(raids[0].blocked), 2966 .entry_node = &(raids[0].node), 2967 }; 2968 vnds_t_info = (structinfo_t) { 2969 .max = MAX_VND, 2970 .entry_size = sizeof vnds[0], 2971 .entry_first = &vnds[0], 2972 .entry_enabled = &(vnds[0].enabled), 2973 .entry_blocked = &(vnds[0].blocked), 2974 .entry_node = &(vnds[0].node), 2975 }; 2976 cgds_t_info = (structinfo_t) { 2977 .max = MAX_CGD, 2978 .entry_size = sizeof cgds[0], 2979 .entry_first = &cgds[0], 2980 .entry_enabled = &(cgds[0].enabled), 2981 .entry_blocked = &(cgds[0].blocked), 2982 .entry_node = &(cgds[0].node), 2983 }; 2984 lvms_t_info = (structinfo_t) { 2985 .max = MAX_LVM_VG, 2986 .entry_size = sizeof lvms[0], 2987 .entry_first = &lvms[0], 2988 .entry_enabled = &(lvms[0].enabled), 2989 .entry_blocked = &(lvms[0].blocked), 2990 .entry_node = NULL, 2991 }; 2992 lv_t_info = (structinfo_t) { 2993 .max = MAX_LVM_LV, 2994 .entry_size = sizeof lvms[0].lv[0], 2995 .entry_first = &lvms[0].lv[0], 2996 .entry_enabled = &(lvms[0].lv[0].size), 2997 .entry_blocked = &(lvms[0].lv[0].blocked), 2998 .parent_size = sizeof lvms[0], 2999 }; 3000 3001 cursel = 0; 3002 changed = 0; 3003 firstrun = 0; 3004 } 3005 3006 do { 3007 menu_num_entries = pm_upddevlist(&(menudesc){.opts = menu_entries}, args); 3008 menu_no = new_menu(MSG_partman_header, 3009 menu_entries, menu_num_entries+1, 1, 1, 0, 75, /* Fixed width */ 3010 MC_ALWAYS_SCROLL | MC_NOBOX | MC_NOCLEAR, 3011 pm_menuin, pm_menufmt, pm_menuout, NULL, MSG_finishpm); 3012 if (menu_no == -1) 3013 args[0].retvalue = -1; 3014 else { 3015 args[0].retvalue = 0; 3016 clear(); 3017 refresh(); 3018 process_menu(menu_no, &args); 3019 free_menu(menu_no); 3020 } 3021 3022 if (args[0].retvalue == 0 && pm->parts != NULL) { 3023 struct install_partition_desc install; 3024 3025 install_desc_from_parts(&install, pm->parts); 3026 if (pm_needsave()) 3027 pm_commit(NULL, NULL); 3028 if (pm_mountall() != 0 || 3029 make_fstab(&install) != 0 || 3030 pm_lastcheck() != 0 || 3031 pm_savebootsector() != 0) { 3032 msg_display(MSG_wannatry); 3033 args[0].retvalue = (ask_yesno(NULL)) ? 1:-1; 3034 } 3035 free_install_desc(&install); 3036 } 3037 } while (args[0].retvalue > 0); 3038 3039 /* retvalue <0 - error, retvalue ==0 - user quits, retvalue >0 - all ok */ 3040 return (args[0].retvalue >= 0)?0:-1; 3041 } 3042 3043 void 3044 update_wedges(const char *disk) 3045 { 3046 check_available_binaries(); 3047 3048 if (!have_dk) 3049 return; 3050 3051 run_program(RUN_SILENT | RUN_ERROR_OK, 3052 "dkctl %s makewedges", disk); 3053 } 3054 3055