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