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