[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.8

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

CVSweb <webmaster@jp.NetBSD.org>