[BACK]Return to partman.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.sbin / sysinst

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>