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

Annotation of src/usr.sbin/sysinst/disks.c, Revision 1.33

1.33    ! christos    1: /*     $NetBSD: disks.c,v 1.32 2019/06/15 08:20:33 martin Exp $ */
1.1       dholland    2:
                      3: /*
                      4:  * Copyright 1997 Piermont Information Systems Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Written by Philip A. Nelson for Piermont Information Systems Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. The name of Piermont Information Systems Inc. may not be used to endorse
                     18:  *    or promote products derived from this software without specific prior
                     19:  *    written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
                     22:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
                     25:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     26:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     27:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     28:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     29:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     30:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     31:  * THE POSSIBILITY OF SUCH DAMAGE.
                     32:  *
                     33:  */
                     34:
                     35: /* disks.c -- routines to deal with finding disks and labeling disks. */
                     36:
                     37:
1.30      martin     38: #include <assert.h>
1.1       dholland   39: #include <errno.h>
1.17      martin     40: #include <inttypes.h>
1.1       dholland   41: #include <stdio.h>
                     42: #include <stdlib.h>
                     43: #include <unistd.h>
                     44: #include <fcntl.h>
1.20      martin     45: #include <fnmatch.h>
1.1       dholland   46: #include <util.h>
1.2       martin     47: #include <uuid.h>
1.30      martin     48: #include <paths.h>
1.1       dholland   49:
                     50: #include <sys/param.h>
                     51: #include <sys/sysctl.h>
                     52: #include <sys/swap.h>
1.30      martin     53: #include <sys/disklabel_gpt.h>
1.1       dholland   54: #include <ufs/ufs/dinode.h>
                     55: #include <ufs/ffs/fs.h>
                     56:
                     57: #include <dev/scsipi/scsipi_all.h>
                     58: #include <sys/scsiio.h>
                     59:
                     60: #include <dev/ata/atareg.h>
                     61: #include <sys/ataio.h>
                     62:
                     63: #include "defs.h"
                     64: #include "md.h"
                     65: #include "msg_defs.h"
                     66: #include "menu_defs.h"
                     67: #include "txtwalk.h"
                     68:
1.31      martin     69: /* #define DEBUG_VERBOSE       1 */
1.30      martin     70:
1.1       dholland   71: /* Disk descriptions */
                     72: struct disk_desc {
                     73:        char    dd_name[SSTRSIZE];
1.29      mrg        74:        char    dd_descr[256];
1.15      martin     75:        bool    dd_no_mbr, dd_no_part;
1.1       dholland   76:        uint    dd_cyl;
                     77:        uint    dd_head;
                     78:        uint    dd_sec;
                     79:        uint    dd_secsize;
1.30      martin     80:        daddr_t dd_totsec;
1.2       martin     81: };
                     82:
1.1       dholland   83: /* Local prototypes */
                     84: static int foundffs(struct data *, size_t);
                     85: #ifdef USE_SYSVBFS
                     86: static int foundsysvbfs(struct data *, size_t);
                     87: #endif
1.30      martin     88: static int fsck_preen(const char *, const char *, bool silent);
                     89: static void fixsb(const char *, const char *);
1.1       dholland   90:
                     91:
                     92: static bool tmpfs_on_var_shm(void);
                     93:
                     94: const char *
1.30      martin     95: getfslabelname(uint f, uint f_version)
1.1       dholland   96: {
1.30      martin     97:        if (f == FS_TMPFS)
                     98:                return "tmpfs";
                     99:        else if (f == FS_MFS)
                    100:                return "mfs";
                    101:        else if (f == FS_BSDFFS && f_version > 0)
                    102:                return f_version == 2 ?
                    103:                    msg_string(MSG_fs_type_ffsv2) : msg_string(MSG_fs_type_ffs);
                    104:        else if (f >= __arraycount(fstypenames) || fstypenames[f] == NULL)
1.1       dholland  105:                return "invalid";
                    106:        return fstypenames[f];
                    107: }
                    108:
                    109: /*
                    110:  * Decide wether we want to mount a tmpfs on /var/shm: we do this always
                    111:  * when the machine has more than 16 MB of user memory. On smaller machines,
                    112:  * shm_open() and friends will not perform well anyway.
                    113:  */
                    114: static bool
                    115: tmpfs_on_var_shm()
                    116: {
                    117:        uint64_t ram;
                    118:        size_t len;
                    119:
                    120:        len = sizeof(ram);
                    121:        if (sysctlbyname("hw.usermem64", &ram, &len, NULL, 0))
                    122:                return false;
                    123:
1.28      martin    124:        return ram > 16 * MEG;
1.1       dholland  125: }
                    126:
                    127: /* from src/sbin/atactl/atactl.c
                    128:  * extract_string: copy a block of bytes out of ataparams and make
                    129:  * a proper string out of it, truncating trailing spaces and preserving
                    130:  * strict typing. And also, not doing unaligned accesses.
                    131:  */
                    132: static void
                    133: ata_extract_string(char *buf, size_t bufmax,
                    134:                   uint8_t *bytes, unsigned numbytes,
                    135:                   int needswap)
                    136: {
                    137:        unsigned i;
                    138:        size_t j;
                    139:        unsigned char ch1, ch2;
                    140:
                    141:        for (i = 0, j = 0; i < numbytes; i += 2) {
                    142:                ch1 = bytes[i];
                    143:                ch2 = bytes[i+1];
                    144:                if (needswap && j < bufmax-1) {
                    145:                        buf[j++] = ch2;
                    146:                }
                    147:                if (j < bufmax-1) {
                    148:                        buf[j++] = ch1;
                    149:                }
                    150:                if (!needswap && j < bufmax-1) {
                    151:                        buf[j++] = ch2;
                    152:                }
                    153:        }
                    154:        while (j > 0 && buf[j-1] == ' ') {
                    155:                j--;
                    156:        }
                    157:        buf[j] = '\0';
                    158: }
                    159:
                    160: /*
                    161:  * from src/sbin/scsictl/scsi_subr.c
                    162:  */
                    163: #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
                    164:
                    165: static void
                    166: scsi_strvis(char *sdst, size_t dlen, const char *ssrc, size_t slen)
                    167: {
                    168:        u_char *dst = (u_char *)sdst;
                    169:        const u_char *src = (const u_char *)ssrc;
                    170:
                    171:        /* Trim leading and trailing blanks and NULs. */
                    172:        while (slen > 0 && STRVIS_ISWHITE(src[0]))
                    173:                ++src, --slen;
                    174:        while (slen > 0 && STRVIS_ISWHITE(src[slen - 1]))
                    175:                --slen;
                    176:
                    177:        while (slen > 0) {
                    178:                if (*src < 0x20 || *src >= 0x80) {
                    179:                        /* non-printable characters */
                    180:                        dlen -= 4;
                    181:                        if (dlen < 1)
                    182:                                break;
                    183:                        *dst++ = '\\';
                    184:                        *dst++ = ((*src & 0300) >> 6) + '0';
                    185:                        *dst++ = ((*src & 0070) >> 3) + '0';
                    186:                        *dst++ = ((*src & 0007) >> 0) + '0';
                    187:                } else if (*src == '\\') {
                    188:                        /* quote characters */
                    189:                        dlen -= 2;
                    190:                        if (dlen < 1)
                    191:                                break;
                    192:                        *dst++ = '\\';
                    193:                        *dst++ = '\\';
                    194:                } else {
                    195:                        /* normal characters */
                    196:                        if (--dlen < 1)
                    197:                                break;
                    198:                        *dst++ = *src;
                    199:                }
                    200:                ++src, --slen;
                    201:        }
                    202:
                    203:        *dst++ = 0;
                    204: }
                    205:
                    206:
                    207: static int
                    208: get_descr_scsi(struct disk_desc *dd, int fd)
                    209: {
                    210:        struct scsipi_inquiry_data inqbuf;
                    211:        struct scsipi_inquiry cmd;
                    212:        scsireq_t req;
                    213:         /* x4 in case every character is escaped, +1 for NUL. */
                    214:        char vendor[(sizeof(inqbuf.vendor) * 4) + 1],
                    215:             product[(sizeof(inqbuf.product) * 4) + 1],
                    216:             revision[(sizeof(inqbuf.revision) * 4) + 1];
                    217:        char size[5];
                    218:        int error;
                    219:
                    220:        memset(&inqbuf, 0, sizeof(inqbuf));
                    221:        memset(&cmd, 0, sizeof(cmd));
                    222:        memset(&req, 0, sizeof(req));
                    223:
                    224:        cmd.opcode = INQUIRY;
                    225:        cmd.length = sizeof(inqbuf);
                    226:        memcpy(req.cmd, &cmd, sizeof(cmd));
                    227:        req.cmdlen = sizeof(cmd);
                    228:        req.databuf = &inqbuf;
                    229:        req.datalen = sizeof(inqbuf);
                    230:        req.timeout = 10000;
                    231:        req.flags = SCCMD_READ;
                    232:        req.senselen = SENSEBUFLEN;
                    233:
                    234:        error = ioctl(fd, SCIOCCOMMAND, &req);
                    235:        if (error == -1 || req.retsts != SCCMD_OK)
                    236:                return 0;
                    237:
                    238:        scsi_strvis(vendor, sizeof(vendor), inqbuf.vendor,
                    239:            sizeof(inqbuf.vendor));
                    240:        scsi_strvis(product, sizeof(product), inqbuf.product,
                    241:            sizeof(inqbuf.product));
                    242:        scsi_strvis(revision, sizeof(revision), inqbuf.revision,
                    243:            sizeof(inqbuf.revision));
                    244:
                    245:        humanize_number(size, sizeof(size),
                    246:            (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec,
                    247:            "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
                    248:
                    249:        snprintf(dd->dd_descr, sizeof(dd->dd_descr),
                    250:            "%s (%s, %s %s)",
                    251:            dd->dd_name, size, vendor, product);
                    252:
                    253:        return 1;
                    254: }
                    255:
                    256: static int
                    257: get_descr_ata(struct disk_desc *dd, int fd)
                    258: {
                    259:        struct atareq req;
                    260:        static union {
                    261:                unsigned char inbuf[DEV_BSIZE];
                    262:                struct ataparams inqbuf;
                    263:        } inbuf;
                    264:        struct ataparams *inqbuf = &inbuf.inqbuf;
                    265:        char model[sizeof(inqbuf->atap_model)+1];
                    266:        char size[5];
                    267:        int error, needswap = 0;
                    268:
                    269:        memset(&inbuf, 0, sizeof(inbuf));
                    270:        memset(&req, 0, sizeof(req));
                    271:
                    272:        req.flags = ATACMD_READ;
                    273:        req.command = WDCC_IDENTIFY;
                    274:        req.databuf = (void *)&inbuf;
                    275:        req.datalen = sizeof(inbuf);
                    276:        req.timeout = 1000;
                    277:
                    278:        error = ioctl(fd, ATAIOCCOMMAND, &req);
                    279:        if (error == -1 || req.retsts != ATACMD_OK)
                    280:                return 0;
                    281:
                    282: #if BYTE_ORDER == LITTLE_ENDIAN
                    283:        /*
                    284:         * On little endian machines, we need to shuffle the string
                    285:         * byte order.  However, we don't have to do this for NEC or
                    286:         * Mitsumi ATAPI devices
                    287:         */
                    288:
                    289:        if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC &&
                    290:              (inqbuf->atap_config & WDC_CFG_ATAPI) &&
                    291:              ((inqbuf->atap_model[0] == 'N' &&
1.10      isaki     292:                inqbuf->atap_model[1] == 'E') ||
1.1       dholland  293:               (inqbuf->atap_model[0] == 'F' &&
1.10      isaki     294:                inqbuf->atap_model[1] == 'X')))) {
1.1       dholland  295:                needswap = 1;
                    296:        }
                    297: #endif
                    298:
                    299:        ata_extract_string(model, sizeof(model),
                    300:            inqbuf->atap_model, sizeof(inqbuf->atap_model), needswap);
                    301:        humanize_number(size, sizeof(size),
                    302:            (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec,
                    303:            "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
                    304:
                    305:        snprintf(dd->dd_descr, sizeof(dd->dd_descr), "%s (%s, %s)",
                    306:            dd->dd_name, size, model);
                    307:
                    308:        return 1;
                    309: }
                    310:
                    311: static void
                    312: get_descr(struct disk_desc *dd)
                    313: {
1.30      martin    314:        char diskpath[MAXPATHLEN], size[5];
1.1       dholland  315:        int fd = -1;
                    316:
                    317:        fd = opendisk(dd->dd_name, O_RDONLY, diskpath, sizeof(diskpath), 0);
                    318:        if (fd < 0)
                    319:                goto done;
                    320:
                    321:        dd->dd_descr[0] = '\0';
                    322:
                    323:        /* try ATA */
                    324:        if (get_descr_ata(dd, fd))
                    325:                goto done;
                    326:        /* try SCSI */
                    327:        if (get_descr_scsi(dd, fd))
                    328:                goto done;
1.30      martin    329:
                    330:        /* XXX: identify for ld @ NVME or microSD */
                    331:
1.2       martin    332:        /* XXX: get description from raid, cgd, vnd... */
1.1       dholland  333:
1.30      martin    334:        /* punt, just give some generic info */
                    335:        humanize_number(size, sizeof(size),
                    336:            (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec,
                    337:            "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
                    338:
                    339:        snprintf(dd->dd_descr, sizeof(dd->dd_descr),
                    340:            "%s (%s)", dd->dd_name, size);
                    341:
1.1       dholland  342: done:
                    343:        if (fd >= 0)
                    344:                close(fd);
                    345: }
                    346:
1.21      martin    347: /*
                    348:  * State for helper callback for get_default_cdrom
                    349:  */
                    350: struct default_cdrom_data {
                    351:        char *device;
                    352:        size_t max_len;
                    353:        bool found;
                    354: };
                    355:
                    356: /*
                    357:  * Helper function for get_default_cdrom, gets passed a device
                    358:  * name and a void pointer to default_cdrom_data.
                    359:  */
                    360: static bool
                    361: get_default_cdrom_helper(void *state, const char *dev)
                    362: {
                    363:        struct default_cdrom_data *data = state;
                    364:
1.25      martin    365:        if (!is_cdrom_device(dev, false))
1.22      martin    366:                return true;
                    367:
1.21      martin    368:        strlcpy(data->device, dev, data->max_len);
1.22      martin    369:        strlcat(data->device, "a", data->max_len); /* default to partition a */
1.21      martin    370:        data->found = true;
                    371:
                    372:        return false;   /* one is enough, stop iteration */
                    373: }
                    374:
                    375: /*
                    376:  * Set the argument to the name of the first CD devices actually
                    377:  * available, leave it unmodified otherwise.
                    378:  * Return true if a device has been found.
1.1       dholland  379:  */
1.18      martin    380: bool
                    381: get_default_cdrom(char *cd, size_t max_len)
1.1       dholland  382: {
1.21      martin    383:        struct default_cdrom_data state;
                    384:
                    385:        state.device = cd;
                    386:        state.max_len = max_len;
                    387:        state.found = false;
                    388:
                    389:        if (enumerate_disks(&state, get_default_cdrom_helper))
                    390:                return state.found;
                    391:
                    392:        return false;
1.1       dholland  393: }
                    394:
1.30      martin    395: static bool
1.15      martin    396: get_wedge_descr(struct disk_desc *dd)
                    397: {
                    398:        struct dkwedge_info dkw;
                    399:        char buf[MAXPATHLEN];
                    400:        int fd;
1.30      martin    401:        bool ok = false;
1.15      martin    402:
                    403:        fd = opendisk(dd->dd_name, O_RDONLY, buf, sizeof(buf), 0);
                    404:        if (fd == -1)
1.30      martin    405:                return false;
1.15      martin    406:
                    407:        if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
                    408:                sprintf(dd->dd_descr, "%s (%s@%s)",
                    409:                    dkw.dkw_wname, dkw.dkw_devname, dkw.dkw_parent);
1.30      martin    410:                ok = true;
1.15      martin    411:        }
                    412:        close(fd);
1.30      martin    413:        return ok;
1.15      martin    414: }
                    415:
                    416: static bool
                    417: get_name_and_parent(const char *dev, char *name, char *parent)
                    418: {
                    419:        struct dkwedge_info dkw;
                    420:        char buf[MAXPATHLEN];
                    421:        int fd;
                    422:        bool res = false;
                    423:
                    424:        fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0);
                    425:        if (fd == -1)
                    426:                return false;
                    427:
                    428:        if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
                    429:                strcpy(name, (const char *)dkw.dkw_wname);
                    430:                strcpy(parent, dkw.dkw_parent);
                    431:                res = true;
                    432:        }
                    433:        close(fd);
                    434:        return res;
                    435: }
                    436:
                    437: static bool
                    438: find_swap_part_on(const char *dev, char *swap_name)
                    439: {
                    440:        struct dkwedge_info *dkw;
                    441:        struct dkwedge_list dkwl;
                    442:        char buf[MAXPATHLEN];
                    443:        size_t bufsize;
                    444:        int fd;
                    445:        u_int i;
                    446:        bool res = false;
                    447:
                    448:        dkw = NULL;
                    449:        dkwl.dkwl_buf = dkw;
                    450:        dkwl.dkwl_bufsize = 0;
                    451:
                    452:        fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0);
                    453:        if (fd == -1)
                    454:                return false;
                    455:
                    456:        for (;;) {
                    457:                if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1) {
                    458:                        dkwl.dkwl_ncopied = 0;
                    459:                        break;
                    460:                }
                    461:                if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied)
                    462:                        break;
                    463:                bufsize = dkwl.dkwl_nwedges * sizeof(*dkw);
                    464:                if (dkwl.dkwl_bufsize < bufsize) {
                    465:                        dkw = realloc(dkwl.dkwl_buf, bufsize);
                    466:                        if (dkw == NULL)
                    467:                                break;
                    468:                        dkwl.dkwl_buf = dkw;
                    469:                        dkwl.dkwl_bufsize = bufsize;
                    470:                }
                    471:        }
                    472:
                    473:        for (i = 0; i < dkwl.dkwl_nwedges; i++) {
                    474:                res = strcmp(dkw[i].dkw_ptype, DKW_PTYPE_SWAP) == 0;
                    475:                if (res) {
                    476:                        strcpy(swap_name, (const char*)dkw[i].dkw_wname);
                    477:                        break;
                    478:                }
                    479:        }
                    480:
                    481:        close(fd);
                    482:
                    483:        return res;
                    484: }
                    485:
                    486: static bool
                    487: is_ffs_wedge(const char *dev)
                    488: {
                    489:        struct dkwedge_info dkw;
                    490:        char buf[MAXPATHLEN];
                    491:        int fd;
                    492:        bool res;
                    493:
                    494:        fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0);
                    495:        if (fd == -1)
                    496:                return false;
                    497:
                    498:        if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == -1)
                    499:                return false;
                    500:
                    501:        res = strcmp(dkw.dkw_ptype, DKW_PTYPE_FFS) == 0;
                    502:        close(fd);
                    503:
                    504:        return res;
                    505: }
                    506:
1.18      martin    507: /*
                    508:  * Does this device match an entry in our default CDROM device list?
1.25      martin    509:  * If looking for install targets, we also flag floopy devices.
1.18      martin    510:  */
1.22      martin    511: bool
1.25      martin    512: is_cdrom_device(const char *dev, bool as_target)
1.18      martin    513: {
1.25      martin    514:        static const char *target_devices[] = {
1.24      martin    515: #ifdef CD_NAMES
                    516:                CD_NAMES
                    517: #endif
                    518: #if defined(CD_NAMES) && defined(FLOPPY_NAMES)
                    519:                ,
                    520: #endif
                    521: #ifdef FLOPPY_NAMES
                    522:                FLOPPY_NAMES
                    523: #endif
                    524: #if defined(CD_NAMES) || defined(FLOPPY_NAMES)
                    525:                ,
                    526: #endif
                    527:                0
                    528:        };
1.25      martin    529:        static const char *src_devices[] = {
                    530: #ifdef CD_NAMES
                    531:                CD_NAMES ,
                    532: #endif
                    533:                0
                    534:        };
1.18      martin    535:
1.25      martin    536:        for (const char **dev_pat = as_target ? target_devices : src_devices;
                    537:             *dev_pat; dev_pat++)
1.20      martin    538:                if (fnmatch(*dev_pat, dev, 0) == 0)
                    539:                        return true;
1.18      martin    540:
                    541:        return false;
                    542: }
                    543:
1.27      martin    544: /* does this device match any entry in the driver list? */
                    545: static bool
                    546: dev_in_list(const char *dev, const char **list)
                    547: {
                    548:
                    549:        for ( ; *list; list++) {
                    550:
                    551:                size_t len = strlen(*list);
                    552:
                    553:                /* start of name matches? */
                    554:                if (strncmp(dev, *list, len) == 0) {
                    555:                        char *endp;
                    556:                        int e;
                    557:
                    558:                        /* remainder of name is a decimal number? */
                    559:                        strtou(dev+len, &endp, 10, 0, INT_MAX, &e);
                    560:                        if (endp && *endp == 0 && e == 0)
                    561:                                return true;
                    562:                }
                    563:        }
                    564:
                    565:        return false;
                    566: }
                    567:
                    568: bool
                    569: is_bootable_device(const char *dev)
                    570: {
                    571:        static const char *non_bootable_devs[] = {
                    572:                "raid", /* bootcode lives outside of raid */
                    573:                "xbd",  /* xen virtual device, can not boot from that */
                    574:                NULL
                    575:        };
                    576:
                    577:        return !dev_in_list(dev, non_bootable_devs);
                    578: }
                    579:
                    580: bool
                    581: is_partitionable_device(const char *dev)
                    582: {
                    583:        static const char *non_partitionable_devs[] = {
                    584:                "dk",   /* this is alreay a partioned slice */
                    585:                NULL
                    586:        };
                    587:
                    588:        return !dev_in_list(dev, non_partitionable_devs);
                    589: }
                    590:
1.18      martin    591: /*
                    592:  * Multi-purpose helper function:
1.21      martin    593:  * iterate all known disks, invoke a callback for each.
                    594:  * Stop iteration when the callback returns false.
                    595:  * Return true when iteration actually happend, false on error.
1.18      martin    596:  */
1.22      martin    597: bool
1.21      martin    598: enumerate_disks(void *state, bool (*func)(void *state, const char *dev))
1.1       dholland  599: {
1.17      martin    600:        static const int mib[] = { CTL_HW, HW_DISKNAMES };
                    601:        static const unsigned int miblen = __arraycount(mib);
                    602:        const char *xd;
1.21      martin    603:        char *disk_names;
1.17      martin    604:        size_t len;
1.1       dholland  605:
1.21      martin    606:        if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1)
                    607:                return false;
1.1       dholland  608:
1.17      martin    609:        disk_names = malloc(len);
                    610:        if (disk_names == NULL)
1.21      martin    611:                return false;
1.17      martin    612:
                    613:        if (sysctl(mib, miblen, disk_names, &len, NULL, 0) == -1) {
                    614:                free(disk_names);
1.21      martin    615:                return false;
1.17      martin    616:        }
1.1       dholland  617:
1.17      martin    618:        for (xd = strtok(disk_names, " "); xd != NULL; xd = strtok(NULL, " ")) {
1.21      martin    619:                if (!(*func)(state, xd))
                    620:                        break;
                    621:        }
                    622:        free(disk_names);
                    623:
                    624:        return true;
                    625: }
                    626:
                    627: /*
                    628:  * Helper state for get_disks
                    629:  */
                    630: struct get_disks_state {
                    631:        int numdisks;
                    632:        struct disk_desc *dd;
                    633:        bool with_non_partitionable;
                    634: };
                    635:
                    636: /*
                    637:  * Helper function for get_disks enumartion
                    638:  */
                    639: static bool
                    640: get_disks_helper(void *arg, const char *dev)
                    641: {
                    642:        struct get_disks_state *state = arg;
1.30      martin    643:        struct disk_geom geo;
1.18      martin    644:
1.21      martin    645:        /* is this a CD device? */
1.25      martin    646:        if (is_cdrom_device(dev, true))
1.21      martin    647:                return true;
                    648:
1.27      martin    649:        memset(state->dd, 0, sizeof(*state->dd));
1.21      martin    650:        strlcpy(state->dd->dd_name, dev, sizeof state->dd->dd_name - 2);
1.27      martin    651:        state->dd->dd_no_mbr = !is_bootable_device(dev);
                    652:        state->dd->dd_no_part = !is_partitionable_device(dev);
1.21      martin    653:
                    654:        if (state->dd->dd_no_part && !state->with_non_partitionable)
                    655:                return true;
1.1       dholland  656:
1.30      martin    657:        if (!get_disk_geom(state->dd->dd_name, &geo)) {
1.21      martin    658:                if (errno == ENOENT)
                    659:                        return true;
                    660:                if (errno != ENOTTY || !state->dd->dd_no_part)
                    661:                        /*
                    662:                         * Allow plain partitions,
                    663:                         * like already existing wedges
                    664:                         * (like dk0) if marked as
                    665:                         * non-partitioning device.
                    666:                         * For all other cases, continue
                    667:                         * with the next disk.
                    668:                         */
                    669:                        return true;
                    670:                if (!is_ffs_wedge(state->dd->dd_name))
                    671:                        return true;
                    672:        }
1.1       dholland  673:
1.21      martin    674:        /*
                    675:         * Exclude a disk mounted as root partition,
                    676:         * in case of install-image on a USB memstick.
                    677:         */
1.23      martin    678:        if (is_active_rootpart(state->dd->dd_name,
                    679:            state->dd->dd_no_part ? -1 : 0))
1.21      martin    680:                return true;
1.17      martin    681:
1.30      martin    682:        state->dd->dd_cyl = geo.dg_ncylinders;
                    683:        state->dd->dd_head = geo.dg_ntracks;
                    684:        state->dd->dd_sec = geo.dg_nsectors;
                    685:        state->dd->dd_secsize = geo.dg_secsize;
                    686:        state->dd->dd_totsec = geo.dg_secperunit;
                    687:
                    688:        if (!state->dd->dd_no_part || !get_wedge_descr(state->dd))
1.21      martin    689:                get_descr(state->dd);
                    690:        state->dd++;
                    691:        state->numdisks++;
                    692:        if (state->numdisks == MAX_DISKS)
                    693:                return false;
                    694:
                    695:        return true;
                    696: }
                    697:
                    698: /*
                    699:  * Get all disk devices that are not CDs.
                    700:  * Optionally leave out those that can not be partitioned further.
                    701:  */
                    702: static int
                    703: get_disks(struct disk_desc *dd, bool with_non_partitionable)
                    704: {
                    705:        struct get_disks_state state;
                    706:
                    707:        /* initialize */
                    708:        state.numdisks = 0;
                    709:        state.dd = dd;
                    710:        state.with_non_partitionable = with_non_partitionable;
                    711:
                    712:        if (enumerate_disks(&state, get_disks_helper))
                    713:                return state.numdisks;
                    714:
                    715:        return 0;
1.1       dholland  716: }
                    717:
1.30      martin    718: #ifdef DEBUG_VERBOSE
                    719: static void
                    720: dump_parts(const struct disk_partitions *parts)
                    721: {
                    722:        fprintf(stderr, "%s partitions on %s:\n",
                    723:            MSG_XLAT(parts->pscheme->short_name), parts->disk);
                    724:
                    725:        for (size_t p = 0; p < parts->num_part; p++) {
                    726:                struct disk_part_info info;
                    727:
                    728:                if (parts->pscheme->get_part_info(
                    729:                    parts, p, &info)) {
                    730:                        fprintf(stderr, " #%zu: start: %" PRIu64 " "
                    731:                            "size: %" PRIu64 ", flags: %x\n",
                    732:                            p, info.start, info.size,
                    733:                            info.flags);
                    734:                        if (info.nat_type)
                    735:                                fprintf(stderr, "\ttype: %s\n",
                    736:                                    info.nat_type->description);
                    737:                } else {
                    738:                        fprintf(stderr, "failed to get info "
                    739:                            "for partition #%zu\n", p);
                    740:                }
                    741:        }
                    742:        fprintf(stderr, "%" PRIu64 " sectors free, disk size %" PRIu64
                    743:            " sectors, %zu partitions used\n", parts->free_space,
                    744:            parts->disk_size, parts->num_part);
                    745: }
                    746: #endif
                    747:
                    748: static bool
                    749: delete_scheme(struct pm_devs *p)
                    750: {
                    751:
                    752:        if (!ask_noyes(MSG_removepartswarn))
                    753:                return false;
                    754:
                    755:        p->parts->pscheme->free(p->parts);
                    756:        p->parts = NULL;
                    757:        return true;
                    758: }
                    759:
                    760:
                    761: static void
                    762: convert_copy(struct disk_partitions *old_parts,
                    763:     struct disk_partitions *new_parts)
                    764: {
                    765:        struct disk_part_info oinfo, ninfo;
                    766:        part_id i;
                    767:
                    768:        for (i = 0; i < old_parts->num_part; i++) {
                    769:                if (!old_parts->pscheme->get_part_info(old_parts, i, &oinfo))
                    770:                        continue;
                    771:
                    772:                if (oinfo.flags & PTI_PSCHEME_INTERNAL)
                    773:                        continue;
                    774:
                    775:                if (oinfo.flags & PTI_SEC_CONTAINER) {
                    776:                        if (old_parts->pscheme->secondary_partitions) {
                    777:                                struct disk_partitions *sec_part =
                    778:                                        old_parts->pscheme->
                    779:                                            secondary_partitions(
1.32      martin    780:                                            old_parts, oinfo.start, false);
1.30      martin    781:                                if (sec_part)
                    782:                                        convert_copy(sec_part, new_parts);
                    783:                        }
                    784:                        continue;
                    785:                }
                    786:
                    787:                if (!new_parts->pscheme->adapt_foreign_part_info(new_parts,
                    788:                            &oinfo, &ninfo))
                    789:                        continue;
                    790:                new_parts->pscheme->add_partition(new_parts, &ninfo, NULL);
                    791:        }
                    792: }
                    793:
                    794: bool
                    795: convert_scheme(struct pm_devs *p, bool is_boot_drive, const char **err_msg)
                    796: {
                    797:        struct disk_partitions *old_parts, *new_parts;
                    798:        const struct disk_partitioning_scheme *new_scheme;
                    799:
                    800:        *err_msg = NULL;
                    801:
                    802:        old_parts = p->parts;
                    803:        new_scheme = select_part_scheme(p, old_parts->pscheme,
                    804:            false, MSG_select_other_partscheme);
                    805:
                    806:        if (new_scheme == NULL)
                    807:                return false;
                    808:
                    809:        new_parts = new_scheme->create_new_for_disk(p->diskdev,
                    810:            0, p->dlsize, p->dlsize, is_boot_drive);
                    811:        if (new_parts == NULL)
                    812:                return false;
                    813:
                    814:        convert_copy(old_parts, new_parts);
                    815:
                    816:        if (new_parts->num_part == 0) {
                    817:                /* need to cleanup */
                    818:                new_parts->pscheme->free(new_parts);
                    819:                return false;
                    820:        }
                    821:
                    822:        old_parts->pscheme->free(old_parts);
                    823:        p->parts = new_parts;
                    824:        return true;
                    825: }
                    826:
1.1       dholland  827: int
                    828: find_disks(const char *doingwhat)
                    829: {
                    830:        struct disk_desc disks[MAX_DISKS];
1.30      martin    831:        menu_ent dsk_menu[__arraycount(disks) + 1]; // + 1 for extended partitioning entry
1.1       dholland  832:        struct disk_desc *disk;
1.15      martin    833:        int i = 0, skipped = 0;
                    834:        int already_found, numdisks, selected_disk = -1;
1.1       dholland  835:        int menu_no;
1.30      martin    836:        struct pm_devs *pm_i, *pm_last = NULL;
                    837:
                    838:        memset(dsk_menu, 0, sizeof(dsk_menu));
1.1       dholland  839:
                    840:        /* Find disks. */
1.21      martin    841:        numdisks = get_disks(disks, partman_go <= 0);
1.1       dholland  842:
                    843:        /* need a redraw here, kernel messages hose everything */
                    844:        touchwin(stdscr);
                    845:        refresh();
                    846:        /* Kill typeahead, it won't be what the user had in mind */
                    847:        fpurge(stdin);
                    848:
1.10      isaki     849:        /*
                    850:         * partman_go: <0 - we want to see menu with extended partitioning
                    851:         *            ==0 - we want to see simple select disk menu
                    852:         *             >0 - we do not want to see any menus, just detect
                    853:         *                  all disks
                    854:         */
1.2       martin    855:        if (partman_go <= 0) {
                    856:                if (numdisks == 0) {
                    857:                        /* No disks found! */
1.30      martin    858:                        hit_enter_to_continue(MSG_nodisk, NULL);
1.2       martin    859:                        /*endwin();*/
                    860:                        return -1;
                    861:                } else {
                    862:                        /* One or more disks found! */
                    863:                        for (i = 0; i < numdisks; i++) {
1.15      martin    864:                                dsk_menu[i].opt_name =
                    865:                                    disks[i].dd_descr;
1.2       martin    866:                                dsk_menu[i].opt_menu = OPT_NOMENU;
                    867:                                dsk_menu[i].opt_flags = OPT_EXIT;
                    868:                                dsk_menu[i].opt_action = set_menu_select;
                    869:                        }
                    870:                        if (partman_go < 0) {
                    871:                                dsk_menu[i].opt_name = MSG_partman;
                    872:                                dsk_menu[i].opt_menu = OPT_NOMENU;
                    873:                                dsk_menu[i].opt_flags = OPT_EXIT;
                    874:                                dsk_menu[i].opt_action = set_menu_select;
                    875:                        }
                    876:                        menu_no = new_menu(MSG_Available_disks,
1.15      martin    877:                                dsk_menu, numdisks
                    878:                                 + ((partman_go<0)?1:0), -1,
                    879:                                 4, 0, 0, MC_SCROLL,
1.2       martin    880:                                NULL, NULL, NULL, NULL, NULL);
                    881:                        if (menu_no == -1)
                    882:                                return -1;
1.33    ! christos  883:                        msg_fmt_display(MSG_ask_disk, "%s", doingwhat);
1.2       martin    884:                        process_menu(menu_no, &selected_disk);
                    885:                        free_menu(menu_no);
                    886:                }
                    887:                if (partman_go < 0 && selected_disk == numdisks) {
                    888:                        partman_go = 1;
1.10      isaki     889:                        return -2;
1.2       martin    890:                } else
                    891:                        partman_go = 0;
                    892:                if (selected_disk < 0 || selected_disk >= numdisks)
1.10      isaki     893:                        return -1;
1.2       martin    894:        }
                    895:
                    896:        /* Fill pm struct with device(s) info */
                    897:        for (i = 0; i < numdisks; i++) {
                    898:                if (! partman_go)
                    899:                        disk = disks + selected_disk;
                    900:                else {
                    901:                        disk = disks + i;
                    902:                        already_found = 0;
                    903:                        SLIST_FOREACH(pm_i, &pm_head, l) {
                    904:                                pm_last = pm_i;
1.10      isaki     905:                                if (!already_found &&
                    906:                                    strcmp(pm_i->diskdev, disk->dd_name) == 0) {
1.2       martin    907:                                        pm_i->found = 1;
                    908:                                        break;
                    909:                                }
                    910:                        }
                    911:                        if (pm_i != NULL && pm_i->found)
                    912:                                /* We already added this device, skipping */
                    913:                                continue;
1.1       dholland  914:                }
1.2       martin    915:                pm = pm_new;
                    916:                pm->found = 1;
1.30      martin    917:                pm->ptstart = 0;
                    918:                pm->ptsize = 0;
1.2       martin    919:                pm->bootable = 0;
                    920:                strlcpy(pm->diskdev, disk->dd_name, sizeof pm->diskdev);
                    921:                strlcpy(pm->diskdev_descr, disk->dd_descr, sizeof pm->diskdev_descr);
                    922:                /* Use as a default disk if the user has the sets on a local disk */
                    923:                strlcpy(localfs_dev, disk->dd_name, sizeof localfs_dev);
                    924:
1.30      martin    925:                /*
                    926:                 * Init disk size and geometry
                    927:                 */
                    928:                pm->sectorsize = disk->dd_secsize;
                    929:                pm->dlcyl = disk->dd_cyl;
                    930:                pm->dlhead = disk->dd_head;
                    931:                pm->dlsec = disk->dd_sec;
                    932:                pm->dlsize = disk->dd_totsec;
                    933:                if (pm->dlsize == 0)
                    934:                        pm->dlsize = disk->dd_cyl * disk->dd_head
                    935:                            * disk->dd_sec;
                    936:
                    937:                pm->parts = partitions_read_disk(pm->diskdev, disk->dd_totsec);
                    938:
                    939: again:
                    940:
                    941: #ifdef DEBUG_VERBOSE
                    942:                if (pm->parts) {
                    943:                        fputs("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", stderr);
                    944:                        dump_parts(pm->parts);
                    945:
                    946:                        if (pm->parts->pscheme->secondary_partitions) {
                    947:                                const struct disk_partitions *sparts =
                    948:                                    pm->parts->pscheme->secondary_partitions(
1.32      martin    949:                                    pm->parts, pm->ptstart, false);
1.30      martin    950:                                if (sparts != NULL)
                    951:                                        dump_parts(sparts);
                    952:                        }
                    953:                }
                    954: #endif
                    955:
                    956:                pm->no_mbr = disk->dd_no_mbr;
1.15      martin    957:                pm->no_part = disk->dd_no_part;
                    958:                if (!pm->no_part) {
                    959:                        pm->sectorsize = disk->dd_secsize;
                    960:                        pm->dlcyl = disk->dd_cyl;
                    961:                        pm->dlhead = disk->dd_head;
                    962:                        pm->dlsec = disk->dd_sec;
                    963:                        pm->dlsize = disk->dd_totsec;
                    964:                        if (pm->dlsize == 0)
1.30      martin    965:                                pm->dlsize = disk->dd_cyl * disk->dd_head
                    966:                                    * disk->dd_sec;
                    967:
                    968:                        if (pm->parts && pm->parts->pscheme->size_limit != 0
                    969:                            && pm->dlsize > pm->parts->pscheme->size_limit
                    970:                            && ! partman_go) {
                    971:
                    972:                                char size[5], limit[5];
                    973:
                    974:                                humanize_number(size, sizeof(size),
                    975:                                    (uint64_t)pm->dlsize * 512U,
                    976:                                    "", HN_AUTOSCALE, HN_B | HN_NOSPACE
                    977:                                    | HN_DECIMAL);
                    978:
                    979:                                humanize_number(limit, sizeof(limit),
                    980:                                    (uint64_t)pm->parts->pscheme->size_limit
                    981:                                        * 512U,
                    982:                                    "", HN_AUTOSCALE, HN_B | HN_NOSPACE
                    983:                                    | HN_DECIMAL);
                    984:
1.15      martin    985:                                if (logfp)
1.30      martin    986:                                        fprintf(logfp,
                    987:                                            "disk %s: is too big (%" PRIu64
                    988:                                            " blocks, %s), will be truncated\n",
                    989:                                                pm->diskdev, pm->dlsize,
                    990:                                                size);
                    991:
                    992:                                msg_display_subst(MSG_toobigdisklabel, 5,
                    993:                                   pm->diskdev,
                    994:                                   msg_string(pm->parts->pscheme->name),
                    995:                                   msg_string(pm->parts->pscheme->short_name),
                    996:                                   size, limit);
                    997:
                    998:                                int sel = -1;
                    999:                                const char *err = NULL;
                   1000:                                process_menu(MENU_convertscheme, &sel);
                   1001:                                if (sel == 1) {
                   1002:                                        if (!delete_scheme(pm)) {
                   1003:                                                return -1;
                   1004:                                        }
                   1005:                                        goto again;
                   1006:                                } else if (sel == 2) {
                   1007:                                        if (!convert_scheme(pm,
                   1008:                                             partman_go < 0, &err)) {
                   1009:                                                if (err != NULL)
                   1010:                                                        err_msg_win(err);
                   1011:                                                return -1;
                   1012:                                        }
                   1013:                                        goto again;
                   1014:                                } else if (sel == 3) {
                   1015:                                        return -1;
                   1016:                                }
                   1017:                                pm->dlsize = pm->parts->pscheme->size_limit;
1.15      martin   1018:                        }
                   1019:                } else {
                   1020:                        pm->sectorsize = 0;
                   1021:                        pm->dlcyl = 0;
                   1022:                        pm->dlhead = 0;
                   1023:                        pm->dlsec = 0;
                   1024:                        pm->dlsize = 0;
                   1025:                        pm->no_mbr = 1;
1.2       martin   1026:                }
                   1027:                pm->dlcylsize = pm->dlhead * pm->dlsec;
                   1028:
                   1029:                if (partman_go) {
                   1030:                        pm_getrefdev(pm_new);
                   1031:                        if (SLIST_EMPTY(&pm_head) || pm_last == NULL)
                   1032:                                 SLIST_INSERT_HEAD(&pm_head, pm_new, l);
                   1033:                        else
                   1034:                                 SLIST_INSERT_AFTER(pm_last, pm_new, l);
1.30      martin   1035:                        pm_new = malloc(sizeof (struct pm_devs));
1.2       martin   1036:                        memset(pm_new, 0, sizeof *pm_new);
                   1037:                } else
1.30      martin   1038:                        /* We are not in partman and do not want to process
                   1039:                         * all devices, exit */
1.2       martin   1040:                        break;
1.1       dholland 1041:        }
                   1042:
1.15      martin   1043:        return numdisks-skipped;
1.2       martin   1044: }
                   1045:
1.30      martin   1046: static int
                   1047: sort_part_usage_by_mount(const void *a, const void *b)
1.2       martin   1048: {
1.30      martin   1049:        const struct part_usage_info *pa = a, *pb = b;
1.15      martin   1050:
1.30      martin   1051:        /* sort all real partitions by mount point */
                   1052:        if ((pa->instflags & PUIINST_MOUNT) &&
                   1053:            (pb->instflags & PUIINST_MOUNT))
                   1054:                return strcmp(pa->mount, pb->mount);
1.15      martin   1055:
1.30      martin   1056:        /* real partitions go first */
                   1057:        if (pa->instflags & PUIINST_MOUNT)
                   1058:                return -1;
                   1059:        if (pb->instflags & PUIINST_MOUNT)
                   1060:                return 1;
1.8       martin   1061:
1.30      martin   1062:        /* arbitrary order for all other partitions */
                   1063:        if (pa->type == PT_swap)
                   1064:                return -1;
                   1065:        if (pb->type == PT_swap)
                   1066:                return 1;
                   1067:        if (pa->type < pb->type)
                   1068:                return -1;
                   1069:        if (pa->type > pb->type)
                   1070:                return 1;
                   1071:        if (pa->cur_part_id < pb->cur_part_id)
                   1072:                return -1;
                   1073:        if (pa->cur_part_id > pb->cur_part_id)
                   1074:                return 1;
                   1075:        return (uintptr_t)a < (uintptr_t)b ? -1 : 1;
1.1       dholland 1076: }
                   1077:
                   1078: int
1.30      martin   1079: make_filesystems(struct install_partition_desc *install)
1.1       dholland 1080: {
1.30      martin   1081:        int error = 0, partno = -1;
                   1082:        char *newfs = NULL, devdev[PATH_MAX], rdev[PATH_MAX];
                   1083:        size_t i;
                   1084:        struct part_usage_info *ptn;
                   1085:        struct disk_partitions *parts;
                   1086:        const char *mnt_opts = NULL, *fsname = NULL;
1.1       dholland 1087:
1.15      martin   1088:        if (pm->no_part) {
                   1089:                /* check if this target device already has a ffs */
1.30      martin   1090:                snprintf(rdev, sizeof rdev, _PATH_DEV "/r%s", pm->diskdev);
                   1091:                error = fsck_preen(rdev, "ffs", true);
1.15      martin   1092:                if (error) {
                   1093:                        if (!ask_noyes(MSG_No_filesystem_newfs))
                   1094:                                return EINVAL;
                   1095:                        error = run_program(RUN_DISPLAY | RUN_PROGRESS,
1.30      martin   1096:                            "/sbin/newfs -V2 -O2 %s", rdev);
1.15      martin   1097:                }
                   1098:
1.30      martin   1099:                md_pre_mount(install);
1.15      martin   1100:
                   1101:                make_target_dir("/");
1.30      martin   1102:
                   1103:                snprintf(devdev, sizeof devdev, _PATH_DEV "%s", pm->diskdev);
1.15      martin   1104:                if (devdev == NULL)
                   1105:                        return (ENOMEM);
                   1106:                error = target_mount_do("-o async", devdev, "/");
                   1107:                if (error) {
1.30      martin   1108:                        msg_display_subst(MSG_mountfail, 2, devdev, "/");
                   1109:                        hit_enter_to_continue(NULL, NULL);
1.15      martin   1110:                }
1.30      martin   1111:
1.15      martin   1112:                return error;
                   1113:        }
                   1114:
1.1       dholland 1115:        /* Making new file systems and mounting them */
                   1116:
                   1117:        /* sort to ensure /usr/local is mounted after /usr (etc) */
1.30      martin   1118:        qsort(install->infos, install->num, sizeof(*install->infos),
                   1119:            sort_part_usage_by_mount);
1.1       dholland 1120:
1.30      martin   1121:        for (i = 0; i < install->num; i++) {
1.1       dholland 1122:                /*
                   1123:                 * newfs and mount. For now, process only BSD filesystems.
                   1124:                 * but if this is the mounted-on root, has no mount
                   1125:                 * point defined, or is marked preserve, don't touch it!
                   1126:                 */
1.30      martin   1127:                ptn = &install->infos[i];
                   1128:                parts = ptn->parts;
1.1       dholland 1129:
1.30      martin   1130:                if (ptn->size == 0 || parts == NULL)
1.1       dholland 1131:                        continue;
                   1132:
1.30      martin   1133:                if (parts->pscheme->get_part_device(parts, ptn->cur_part_id,
                   1134:                    devdev, sizeof devdev, &partno, parent_device_only, false)
                   1135:                    && is_active_rootpart(devdev, partno))
                   1136:                        continue;
                   1137:
                   1138:                if ((ptn->instflags & PUIINST_MOUNT) == 0)
1.1       dholland 1139:                        /* No mount point */
                   1140:                        continue;
                   1141:
1.30      martin   1142:                parts->pscheme->get_part_device(parts, ptn->cur_part_id,
                   1143:                    devdev, sizeof devdev, &partno, plain_name, true);
                   1144:
                   1145:                parts->pscheme->get_part_device(parts, ptn->cur_part_id,
                   1146:                    rdev, sizeof rdev, &partno, raw_dev_name, true);
1.2       martin   1147:
1.1       dholland 1148:                newfs = NULL;
1.30      martin   1149:                switch (ptn->fs_type) {
1.1       dholland 1150:                case FS_APPLEUFS:
1.30      martin   1151:                        asprintf(&newfs, "/sbin/newfs");
                   1152:                        mnt_opts = "-tffs -o async";
                   1153:                        fsname = "ffs";
1.1       dholland 1154:                        break;
                   1155:                case FS_BSDFFS:
                   1156:                        asprintf(&newfs,
1.30      martin   1157:                            "/sbin/newfs -V2 -O %d",
                   1158:                            ptn->fs_version == 2 ? 2 : 1);
                   1159:                        if (ptn->mountflags & PUIMNT_LOG)
                   1160:                                mnt_opts = "-tffs -o log";
1.1       dholland 1161:                        else
1.30      martin   1162:                                mnt_opts = "-tffs -o async";
                   1163:                        fsname = "ffs";
1.1       dholland 1164:                        break;
                   1165:                case FS_BSDLFS:
1.30      martin   1166:                        asprintf(&newfs, "/sbin/newfs_lfs");
                   1167:                        mnt_opts = "-tlfs";
                   1168:                        fsname = "lfs";
1.1       dholland 1169:                        break;
                   1170:                case FS_MSDOS:
                   1171:                        asprintf(&newfs, "/sbin/newfs_msdos");
1.30      martin   1172:                        mnt_opts = "-tmsdos";
                   1173:                        fsname = "msdos";
1.1       dholland 1174:                        break;
                   1175: #ifdef USE_SYSVBFS
                   1176:                case FS_SYSVBFS:
                   1177:                        asprintf(&newfs, "/sbin/newfs_sysvbfs");
1.30      martin   1178:                        mnt_opts = "-tsysvbfs";
                   1179:                        fsname = "sysvbfs";
1.1       dholland 1180:                        break;
                   1181: #endif
                   1182: #ifdef USE_EXT2FS
                   1183:                case FS_EX2FS:
                   1184:                        asprintf(&newfs, "/sbin/newfs_ext2fs");
1.30      martin   1185:                        mnt_opts = "-text2fs";
                   1186:                        fsname = "ext2fs";
1.1       dholland 1187:                        break;
                   1188: #endif
                   1189:                }
1.30      martin   1190:                if ((ptn->instflags & PUIINST_NEWFS) && newfs != NULL) {
                   1191:                        if (ptn->fs_type == FS_MSDOS) {
1.1       dholland 1192:                                /* newfs only if mount fails */
                   1193:                                if (run_program(RUN_SILENT | RUN_ERROR_OK,
1.30      martin   1194:                                    "mount -rt msdos %s /mnt2", devdev) != 0)
1.1       dholland 1195:                                        error = run_program(
                   1196:                                            RUN_DISPLAY | RUN_PROGRESS,
1.30      martin   1197:                                            "%s %s",
                   1198:                                            newfs, rdev);
1.1       dholland 1199:                                else {
1.10      isaki    1200:                                        run_program(RUN_SILENT | RUN_ERROR_OK,
1.1       dholland 1201:                                            "umount /mnt2");
                   1202:                                        error = 0;
                   1203:                                }
1.30      martin   1204:                        } else {
                   1205:                                error = run_program(RUN_DISPLAY | RUN_PROGRESS,
                   1206:                            "%s %s", newfs, rdev);
                   1207:                        }
1.1       dholland 1208:                } else {
                   1209:                        /* We'd better check it isn't dirty */
1.30      martin   1210:                        error = fsck_preen(devdev, fsname, false);
1.1       dholland 1211:                }
                   1212:                free(newfs);
1.30      martin   1213:                if (error != 0)
1.1       dholland 1214:                        return error;
                   1215:
1.30      martin   1216:                ptn->instflags &= ~PUIINST_NEWFS;
                   1217:                md_pre_mount(install);
1.1       dholland 1218:
1.30      martin   1219:                if (partman_go == 0 && (ptn->instflags & PUIINST_MOUNT) &&
                   1220:                                mnt_opts != NULL) {
                   1221:                        make_target_dir(ptn->mount);
                   1222:                        error = target_mount_do(mnt_opts, devdev,
                   1223:                            ptn->mount);
1.1       dholland 1224:                        if (error) {
1.30      martin   1225:                                msg_display_subst(MSG_mountfail, 2, devdev,
                   1226:                                    ptn->mount);
                   1227:                                hit_enter_to_continue(NULL, NULL);
1.1       dholland 1228:                                return error;
                   1229:                        }
                   1230:                }
                   1231:        }
                   1232:        return 0;
                   1233: }
                   1234:
                   1235: int
1.30      martin   1236: make_fstab(struct install_partition_desc *install)
1.1       dholland 1237: {
                   1238:        FILE *f;
1.30      martin   1239:        const char *dump_dev = NULL;
                   1240:        const char *dev;
                   1241:        char dev_buf[PATH_MAX], swap_dev[PATH_MAX];
                   1242:
                   1243:        swap_dev[0] = 0;
1.1       dholland 1244:
                   1245:        /* Create the fstab. */
                   1246:        make_target_dir("/etc");
                   1247:        f = target_fopen("/etc/fstab", "w");
1.2       martin   1248:        scripting_fprintf(NULL, "cat <<EOF >%s/etc/fstab\n", target_prefix());
                   1249:
1.1       dholland 1250:        if (logfp)
                   1251:                (void)fprintf(logfp,
1.30      martin   1252:                    "Making %s/etc/fstab (%s).\n", target_prefix(),
                   1253:                    pm->diskdev);
1.10      isaki    1254:
1.1       dholland 1255:        if (f == NULL) {
                   1256:                msg_display(MSG_createfstab);
                   1257:                if (logfp)
                   1258:                        (void)fprintf(logfp, "Failed to make /etc/fstab!\n");
1.30      martin   1259:                hit_enter_to_continue(NULL, NULL);
1.2       martin   1260: #ifndef DEBUG
1.1       dholland 1261:                return 1;
                   1262: #else
                   1263:                f = stdout;
                   1264: #endif
                   1265:        }
                   1266:
1.16      martin   1267:        scripting_fprintf(f, "# NetBSD /etc/fstab\n# See /usr/share/examples/"
                   1268:                        "fstab/ for more examples.\n");
1.15      martin   1269:
                   1270:        if (pm->no_part) {
                   1271:                /* single dk? target */
                   1272:                char buf[200], parent[200], swap[200], *prompt;
                   1273:                int res;
                   1274:
                   1275:                if (!get_name_and_parent(pm->diskdev, buf, parent))
                   1276:                        goto done_with_disks;
                   1277:                scripting_fprintf(f, "NAME=%s\t/\tffs\trw\t\t1 1\n",
                   1278:                    buf);
                   1279:                if (!find_swap_part_on(parent, swap))
                   1280:                        goto done_with_disks;
1.30      martin   1281:                const char *args[] = { parent, swap };
                   1282:                prompt = str_arg_subst(msg_string(MSG_Auto_add_swap_part),
                   1283:                    __arraycount(args), args);
1.15      martin   1284:                res = ask_yesno(prompt);
                   1285:                free(prompt);
                   1286:                if (res)
                   1287:                        scripting_fprintf(f, "NAME=%s\tnone"
                   1288:                            "\tswap\tsw,dp\t\t0 0\n", swap);
                   1289:                goto done_with_disks;
                   1290:        }
                   1291:
1.30      martin   1292:        for (size_t i = 0; i < install->num; i++) {
                   1293:
                   1294:                const struct part_usage_info *ptn = &install->infos[i];
                   1295:
                   1296:                if (ptn->type != PT_swap &&
                   1297:                    (ptn->instflags & PUIINST_MOUNT) == 0)
                   1298:                        continue;
                   1299:
                   1300:                const char *s = "";
                   1301:                const char *mp = ptn->mount;
                   1302:                const char *fstype = "ffs";
                   1303:                int fsck_pass = 0, dump_freq = 0;
                   1304:
                   1305:                if (ptn->parts->pscheme->get_part_device(ptn->parts,
                   1306:                            ptn->cur_part_id, dev_buf, sizeof dev_buf, NULL,
                   1307:                            logical_name, true))
                   1308:                        dev = dev_buf;
                   1309:                else
                   1310:                        dev = NULL;
                   1311:
                   1312:                if (!*mp) {
                   1313:                        /*
                   1314:                         * No mount point specified, comment out line and
                   1315:                         * use /mnt as a placeholder for the mount point.
                   1316:                         */
                   1317:                        s = "# ";
                   1318:                        mp = "/mnt";
                   1319:                }
                   1320:
                   1321:                switch (ptn->fs_type) {
                   1322:                case FS_UNUSED:
                   1323:                        continue;
                   1324:                case FS_BSDLFS:
                   1325:                        /* If there is no LFS, just comment it out. */
                   1326:                        if (!check_lfs_progs())
1.1       dholland 1327:                                s = "# ";
1.30      martin   1328:                        fstype = "lfs";
                   1329:                        /* FALLTHROUGH */
                   1330:                case FS_BSDFFS:
                   1331:                        fsck_pass = (strcmp(mp, "/") == 0) ? 1 : 2;
                   1332:                        dump_freq = 1;
                   1333:                        break;
                   1334:                case FS_MSDOS:
                   1335:                        fstype = "msdos";
                   1336:                        break;
                   1337:                case FS_SWAP:
                   1338:                        if (swap_dev[0] == 0) {
                   1339:                                strncpy(swap_dev, dev, sizeof swap_dev);
                   1340:                                dump_dev = ",dp";
                   1341:                        } else {
                   1342:                                dump_dev = "";
1.1       dholland 1343:                        }
1.30      martin   1344:                        scripting_fprintf(f, "%s\t\tnone\tswap\tsw%s\t\t 0 0\n",
                   1345:                                dev, dump_dev);
                   1346:                        continue;
1.1       dholland 1347: #ifdef USE_SYSVBFS
1.30      martin   1348:                case FS_SYSVBFS:
                   1349:                        fstype = "sysvbfs";
                   1350:                        make_target_dir("/stand");
                   1351:                        break;
1.1       dholland 1352: #endif
1.30      martin   1353:                default:
                   1354:                        fstype = "???";
                   1355:                        s = "# ";
                   1356:                        break;
1.2       martin   1357:                }
1.30      martin   1358:                /* The code that remounts root rw doesn't check the partition */
                   1359:                if (strcmp(mp, "/") == 0 &&
                   1360:                    (ptn->instflags & PUIINST_MOUNT) == 0)
                   1361:                        s = "# ";
                   1362:
                   1363:                scripting_fprintf(f,
                   1364:                  "%s%s\t\t%s\t%s\trw%s%s%s%s%s%s%s%s\t\t %d %d\n",
                   1365:                   s, dev, mp, fstype,
                   1366:                   ptn->mountflags & PUIMNT_LOG ? ",log" : "",
                   1367:                   ptn->mountflags & PUIMNT_NOAUTO ? "" : ",noauto",
                   1368:                   ptn->mountflags & PUIMNT_ASYNC ? ",async" : "",
                   1369:                   ptn->mountflags & PUIMNT_NOATIME ? ",noatime" : "",
                   1370:                   ptn->mountflags & PUIMNT_NODEV ? ",nodev" : "",
                   1371:                   ptn->mountflags & PUIMNT_NODEVMTIME ? ",nodevmtime" : "",
                   1372:                   ptn->mountflags & PUIMNT_NOEXEC ? ",noexec" : "",
                   1373:                   ptn->mountflags & PUIMNT_NOSUID ? ",nosuid" : "",
                   1374:                   dump_freq, fsck_pass);
1.1       dholland 1375:        }
1.30      martin   1376:
1.15      martin   1377: done_with_disks:
1.30      martin   1378:        if (tmp_ramdisk_size > 0) {
1.1       dholland 1379: #ifdef HAVE_TMPFS
                   1380:                scripting_fprintf(f, "tmpfs\t\t/tmp\ttmpfs\trw,-m=1777,-s=%"
1.30      martin   1381:                    PRIu64 "\n",
1.1       dholland 1382:                    tmp_ramdisk_size * 512);
                   1383: #else
1.30      martin   1384:                if (swap_dev[0] != 0)
                   1385:                        scripting_fprintf(f, "%s\t\t/tmp\tmfs\trw,-s=%"
                   1386:                            PRIu64 "\n", swap_dev, tmp_ramdisk_size);
1.1       dholland 1387:                else
                   1388:                        scripting_fprintf(f, "swap\t\t/tmp\tmfs\trw,-s=%"
1.30      martin   1389:                            PRIu64 "\n", tmp_ramdisk_size);
1.1       dholland 1390: #endif
                   1391:        }
                   1392:
1.18      martin   1393:        if (cdrom_dev[0] == 0)
                   1394:                get_default_cdrom(cdrom_dev, sizeof(cdrom_dev));
                   1395:
1.1       dholland 1396:        /* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */
                   1397:        scripting_fprintf(f, "kernfs\t\t/kern\tkernfs\trw\n");
                   1398:        scripting_fprintf(f, "ptyfs\t\t/dev/pts\tptyfs\trw\n");
                   1399:        scripting_fprintf(f, "procfs\t\t/proc\tprocfs\trw\n");
                   1400:        scripting_fprintf(f, "/dev/%s\t\t/cdrom\tcd9660\tro,noauto\n",
1.18      martin   1401:            cdrom_dev);
1.1       dholland 1402:        scripting_fprintf(f, "%stmpfs\t\t/var/shm\ttmpfs\trw,-m1777,-sram%%25\n",
                   1403:            tmpfs_on_var_shm() ? "" : "#");
                   1404:        make_target_dir("/kern");
                   1405:        make_target_dir("/proc");
                   1406:        make_target_dir("/dev/pts");
                   1407:        make_target_dir("/cdrom");
                   1408:        make_target_dir("/var/shm");
                   1409:
                   1410:        scripting_fprintf(NULL, "EOF\n");
                   1411:
                   1412:        fclose(f);
                   1413:        fflush(NULL);
                   1414:        return 0;
                   1415: }
                   1416:
                   1417:
                   1418:
                   1419: static int
                   1420: /*ARGSUSED*/
                   1421: foundffs(struct data *list, size_t num)
                   1422: {
                   1423:        int error;
                   1424:
                   1425:        if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 ||
                   1426:            strstr(list[2].u.s_val, "noauto") != NULL)
                   1427:                return 0;
                   1428:
1.30      martin   1429:        error = fsck_preen(list[0].u.s_val, "ffs", false);
1.1       dholland 1430:        if (error != 0)
                   1431:                return error;
                   1432:
1.30      martin   1433:        error = target_mount("", list[0].u.s_val, list[1].u.s_val);
1.1       dholland 1434:        if (error != 0) {
1.33    ! christos 1435:                msg_fmt_display(MSG_mount_failed, "%s", list[0].u.s_val);
1.9       martin   1436:                if (!ask_noyes(NULL))
1.1       dholland 1437:                        return error;
                   1438:        }
                   1439:        return 0;
                   1440: }
                   1441:
                   1442: #ifdef USE_SYSVBFS
                   1443: static int
                   1444: /*ARGSUSED*/
                   1445: foundsysvbfs(struct data *list, size_t num)
                   1446: {
                   1447:        int error;
                   1448:
                   1449:        if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 ||
                   1450:            strstr(list[2].u.s_val, "noauto") != NULL)
                   1451:                return 0;
                   1452:
1.30      martin   1453:        error = target_mount("", list[0].u.s_val, list[1].u.s_val);
1.1       dholland 1454:        if (error != 0)
                   1455:                return error;
                   1456:        return 0;
                   1457: }
                   1458: #endif
                   1459:
                   1460: /*
                   1461:  * Do an fsck. On failure, inform the user by showing a warning
                   1462:  * message and doing menu_ok() before proceeding.
1.30      martin   1463:  * The device passed should be the full qualified path to raw disk
                   1464:  * (e.g. /dev/rwd0a).
1.1       dholland 1465:  * Returns 0 on success, or nonzero return code from fsck() on failure.
                   1466:  */
                   1467: static int
1.30      martin   1468: fsck_preen(const char *disk, const char *fsname, bool silent)
1.1       dholland 1469: {
1.30      martin   1470:        char *prog, err[12];
1.1       dholland 1471:        int error;
                   1472:
                   1473:        if (fsname == NULL)
                   1474:                return 0;
                   1475:        /* first, check if fsck program exists, if not, assume ok */
                   1476:        asprintf(&prog, "/sbin/fsck_%s", fsname);
                   1477:        if (prog == NULL)
                   1478:                return 0;
1.12      martin   1479:        if (access(prog, X_OK) != 0) {
                   1480:                free(prog);
1.1       dholland 1481:                return 0;
1.12      martin   1482:        }
1.1       dholland 1483:        if (!strcmp(fsname,"ffs"))
1.30      martin   1484:                fixsb(prog, disk);
                   1485:        error = run_program(silent? RUN_SILENT|RUN_ERROR_OK : 0, "%s -p -q %s", prog, disk);
1.1       dholland 1486:        free(prog);
1.15      martin   1487:        if (error != 0 && !silent) {
1.30      martin   1488:                sprintf(err, "%d", error);
                   1489:                msg_display_subst(msg_string(MSG_badfs), 3,
                   1490:                    disk, fsname, err);
1.9       martin   1491:                if (ask_noyes(NULL))
1.1       dholland 1492:                        error = 0;
                   1493:                /* XXX at this point maybe we should run a full fsck? */
                   1494:        }
                   1495:        return error;
                   1496: }
                   1497:
                   1498: /* This performs the same function as the etc/rc.d/fixsb script
                   1499:  * which attempts to correct problems with ffs1 filesystems
                   1500:  * which may have been introduced by booting a netbsd-current kernel
                   1501:  * from between April of 2003 and January 2004. For more information
                   1502:  * This script was developed as a response to NetBSD pr install/25138
                   1503:  * Additional prs regarding the original issue include:
                   1504:  *  bin/17910 kern/21283 kern/21404 port-macppc/23925 port-macppc/23926
                   1505:  */
                   1506: static void
1.30      martin   1507: fixsb(const char *prog, const char *disk)
1.1       dholland 1508: {
                   1509:        int fd;
                   1510:        int rval;
                   1511:        union {
                   1512:                struct fs fs;
                   1513:                char buf[SBLOCKSIZE];
                   1514:        } sblk;
                   1515:        struct fs *fs = &sblk.fs;
                   1516:
1.30      martin   1517:        fd = open(disk, O_RDONLY);
1.1       dholland 1518:        if (fd == -1)
                   1519:                return;
                   1520:
                   1521:        /* Read ffsv1 main superblock */
                   1522:        rval = pread(fd, sblk.buf, sizeof sblk.buf, SBLOCK_UFS1);
                   1523:        close(fd);
                   1524:        if (rval != sizeof sblk.buf)
                   1525:                return;
                   1526:
                   1527:        if (fs->fs_magic != FS_UFS1_MAGIC &&
                   1528:            fs->fs_magic != FS_UFS1_MAGIC_SWAPPED)
                   1529:                /* Not FFSv1 */
                   1530:                return;
                   1531:        if (fs->fs_old_flags & FS_FLAGS_UPDATED)
                   1532:                /* properly updated fslevel 4 */
                   1533:                return;
                   1534:        if (fs->fs_bsize != fs->fs_maxbsize)
                   1535:                /* not messed up */
                   1536:                return;
                   1537:
                   1538:        /*
                   1539:         * OK we have a munged fs, first 'upgrade' to fslevel 4,
                   1540:         * We specify -b16 in order to stop fsck bleating that the
                   1541:         * sb doesn't match the first alternate.
                   1542:         */
                   1543:        run_program(RUN_DISPLAY | RUN_PROGRESS,
1.30      martin   1544:            "%s -p -b 16 -c 4 %s", prog, disk);
1.1       dholland 1545:        /* Then downgrade to fslevel 3 */
                   1546:        run_program(RUN_DISPLAY | RUN_PROGRESS,
1.30      martin   1547:            "%s -p -c 3 %s", prog, disk);
1.1       dholland 1548: }
                   1549:
                   1550: /*
                   1551:  * fsck and mount the root partition.
1.30      martin   1552:  * devdev is the fully qualified block device name.
1.1       dholland 1553:  */
                   1554: static int
1.30      martin   1555: mount_root(const char *devdev, struct install_partition_desc *install)
1.1       dholland 1556: {
                   1557:        int     error;
                   1558:
1.30      martin   1559:        error = fsck_preen(devdev, "ffs", false);
1.1       dholland 1560:        if (error != 0)
                   1561:                return error;
                   1562:
1.30      martin   1563:        md_pre_mount(install);
1.1       dholland 1564:
1.30      martin   1565:        /* Mount devdev on target's "".
1.1       dholland 1566:         * If we pass "" as mount-on, Prefixing will DTRT.
                   1567:         * for now, use no options.
                   1568:         * XXX consider -o remount in case target root is
                   1569:         * current root, still readonly from single-user?
                   1570:         */
1.30      martin   1571:        return target_mount("", devdev, "");
1.1       dholland 1572: }
                   1573:
                   1574: /* Get information on the file systems mounted from the root filesystem.
                   1575:  * Offer to convert them into 4.4BSD inodes if they are not 4.4BSD
                   1576:  * inodes.  Fsck them.  Mount them.
                   1577:  */
                   1578:
                   1579: int
1.30      martin   1580: mount_disks(struct install_partition_desc *install)
1.1       dholland 1581: {
                   1582:        char *fstab;
                   1583:        int   fstabsize;
                   1584:        int   error;
1.30      martin   1585:        char devdev[PATH_MAX];
1.1       dholland 1586:
                   1587:        static struct lookfor fstabbuf[] = {
                   1588:                {"/dev/", "/dev/%s %s ffs %s", "c", NULL, 0, 0, foundffs},
                   1589:                {"/dev/", "/dev/%s %s ufs %s", "c", NULL, 0, 0, foundffs},
                   1590: #ifdef USE_SYSVBFS
                   1591:                {"/dev/", "/dev/%s %s sysvbfs %s", "c", NULL, 0, 0,
                   1592:                    foundsysvbfs},
                   1593: #endif
                   1594:        };
                   1595:        static size_t numfstabbuf = sizeof(fstabbuf) / sizeof(struct lookfor);
                   1596:
                   1597:        /* First the root device. */
                   1598:        if (target_already_root())
                   1599:                /* avoid needing to call target_already_root() again */
                   1600:                targetroot_mnt[0] = 0;
                   1601:        else {
1.30      martin   1602:                assert(install != NULL && install->num > 0);
                   1603:                assert(strcmp(install->infos[0].mount, "/") == 0);
                   1604:                if (!install->infos[0].parts->pscheme->get_part_device(
                   1605:                    install->infos[0].parts, install->infos[0].cur_part_id,
                   1606:                    devdev, sizeof devdev, NULL, plain_name, true))
                   1607:                        return -1;
                   1608:                error = mount_root(devdev, install);
1.1       dholland 1609:                if (error != 0 && error != EBUSY)
                   1610:                        return -1;
                   1611:        }
                   1612:
                   1613:        /* Check the target /etc/fstab exists before trying to parse it. */
                   1614:        if (target_dir_exists_p("/etc") == 0 ||
                   1615:            target_file_exists_p("/etc/fstab") == 0) {
1.33    ! christos 1616:                msg_fmt_display(MSG_noetcfstab, "%s", pm->diskdev);
1.30      martin   1617:                hit_enter_to_continue(NULL, NULL);
1.1       dholland 1618:                return -1;
                   1619:        }
                   1620:
                   1621:
                   1622:        /* Get fstab entries from the target-root /etc/fstab. */
                   1623:        fstabsize = target_collect_file(T_FILE, &fstab, "/etc/fstab");
                   1624:        if (fstabsize < 0) {
                   1625:                /* error ! */
1.33    ! christos 1626:                msg_fmt_display(MSG_badetcfstab, "%s", pm->diskdev);
1.30      martin   1627:                hit_enter_to_continue(NULL, NULL);
1.2       martin   1628:                return -2;
1.1       dholland 1629:        }
                   1630:        error = walk(fstab, (size_t)fstabsize, fstabbuf, numfstabbuf);
                   1631:        free(fstab);
                   1632:
                   1633:        return error;
                   1634: }
                   1635:
                   1636: int
1.30      martin   1637: set_swap_if_low_ram(struct install_partition_desc *install)
1.10      isaki    1638: {
                   1639:        if (get_ramsize() <= 32)
1.30      martin   1640:                return set_swap(install);
1.10      isaki    1641:        return 0;
1.7       abs      1642: }
                   1643:
                   1644: int
1.30      martin   1645: set_swap(struct install_partition_desc *install)
1.1       dholland 1646: {
1.30      martin   1647:        size_t i;
                   1648:        char dev_buf[PATH_MAX];
1.1       dholland 1649:        int rval;
                   1650:
1.30      martin   1651:        for (i = 0; i < install->num; i++) {
                   1652:                if (install->infos[i].type == PT_swap)
                   1653:                        break;
                   1654:        }
                   1655:        if (i >= install->num)
                   1656:                return 0;
1.1       dholland 1657:
1.30      martin   1658:        if (!install->infos[i].parts->pscheme->get_part_device(
                   1659:            install->infos[i].parts, install->infos[i].cur_part_id, dev_buf,
                   1660:            sizeof dev_buf, NULL, plain_name, true))
                   1661:                return -1;
                   1662:
                   1663:        rval = swapctl(SWAP_ON, dev_buf, 0);
                   1664:        if (rval != 0)
                   1665:                return -1;
1.1       dholland 1666:
                   1667:        return 0;
                   1668: }
                   1669:
                   1670: int
                   1671: check_swap(const char *disk, int remove_swap)
                   1672: {
                   1673:        struct swapent *swap;
                   1674:        char *cp;
                   1675:        int nswap;
                   1676:        int l;
                   1677:        int rval = 0;
                   1678:
                   1679:        nswap = swapctl(SWAP_NSWAP, 0, 0);
                   1680:        if (nswap <= 0)
                   1681:                return 0;
                   1682:
                   1683:        swap = malloc(nswap * sizeof *swap);
                   1684:        if (swap == NULL)
                   1685:                return -1;
                   1686:
                   1687:        nswap = swapctl(SWAP_STATS, swap, nswap);
                   1688:        if (nswap < 0)
                   1689:                goto bad_swap;
                   1690:
                   1691:        l = strlen(disk);
                   1692:        while (--nswap >= 0) {
                   1693:                /* Should we check the se_dev or se_path? */
                   1694:                cp = swap[nswap].se_path;
                   1695:                if (memcmp(cp, "/dev/", 5) != 0)
                   1696:                        continue;
                   1697:                if (memcmp(cp + 5, disk, l) != 0)
                   1698:                        continue;
                   1699:                if (!isalpha(*(unsigned char *)(cp + 5 + l)))
                   1700:                        continue;
                   1701:                if (cp[5 + l + 1] != 0)
                   1702:                        continue;
                   1703:                /* ok path looks like it is for this device */
                   1704:                if (!remove_swap) {
                   1705:                        /* count active swap areas */
                   1706:                        rval++;
                   1707:                        continue;
                   1708:                }
                   1709:                if (swapctl(SWAP_OFF, cp, 0) == -1)
                   1710:                        rval = -1;
                   1711:        }
                   1712:
                   1713:     done:
                   1714:        free(swap);
                   1715:        return rval;
                   1716:
                   1717:     bad_swap:
                   1718:        rval = -1;
                   1719:        goto done;
                   1720: }
                   1721:
                   1722: #ifdef HAVE_BOOTXX_xFS
                   1723: char *
1.30      martin   1724: bootxx_name(struct install_partition_desc *install)
1.1       dholland 1725: {
                   1726:        int fstype;
                   1727:        const char *bootxxname;
                   1728:        char *bootxx;
                   1729:
                   1730:        /* check we have boot code for the root partition type */
1.30      martin   1731:        fstype = install->infos[0].fs_type;
1.1       dholland 1732:        switch (fstype) {
                   1733: #if defined(BOOTXX_FFSV1) || defined(BOOTXX_FFSV2)
                   1734:        case FS_BSDFFS:
1.30      martin   1735:                if (install->infos[0].fs_version == 2) {
1.1       dholland 1736: #ifdef BOOTXX_FFSV2
                   1737:                        bootxxname = BOOTXX_FFSV2;
                   1738: #else
                   1739:                        bootxxname = NULL;
                   1740: #endif
                   1741:                } else {
                   1742: #ifdef BOOTXX_FFSV1
                   1743:                        bootxxname = BOOTXX_FFSV1;
                   1744: #else
                   1745:                        bootxxname = NULL;
                   1746: #endif
                   1747:                }
                   1748:                break;
                   1749: #endif
1.11      pgoyette 1750: #ifdef BOOTXX_LFSV2
1.1       dholland 1751:        case FS_BSDLFS:
1.11      pgoyette 1752:                bootxxname = BOOTXX_LFSV2;
1.1       dholland 1753:                break;
                   1754: #endif
                   1755:        default:
                   1756:                bootxxname = NULL;
                   1757:                break;
                   1758:        }
                   1759:
                   1760:        if (bootxxname == NULL)
                   1761:                return NULL;
                   1762:
                   1763:        asprintf(&bootxx, "%s/%s", BOOTXXDIR, bootxxname);
                   1764:        return bootxx;
                   1765: }
                   1766: #endif
1.2       martin   1767:
                   1768: /* from dkctl.c */
                   1769: static int
                   1770: get_dkwedges_sort(const void *a, const void *b)
                   1771: {
                   1772:        const struct dkwedge_info *dkwa = a, *dkwb = b;
                   1773:        const daddr_t oa = dkwa->dkw_offset, ob = dkwb->dkw_offset;
                   1774:        return (oa < ob) ? -1 : (oa > ob) ? 1 : 0;
                   1775: }
                   1776:
                   1777: int
                   1778: get_dkwedges(struct dkwedge_info **dkw, const char *diskdev)
                   1779: {
                   1780:        int fd;
                   1781:        char buf[STRSIZE];
                   1782:        size_t bufsize;
                   1783:        struct dkwedge_list dkwl;
                   1784:
                   1785:        *dkw = NULL;
                   1786:        dkwl.dkwl_buf = *dkw;
                   1787:        dkwl.dkwl_bufsize = 0;
                   1788:        fd = opendisk(diskdev, O_RDONLY, buf, STRSIZE, 0);
                   1789:        if (fd < 0)
                   1790:                return -1;
                   1791:
                   1792:        for (;;) {
                   1793:                if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1)
                   1794:                        return -2;
                   1795:                if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied)
                   1796:                        break;
                   1797:                bufsize = dkwl.dkwl_nwedges * sizeof(**dkw);
                   1798:                if (dkwl.dkwl_bufsize < bufsize) {
                   1799:                        *dkw = realloc(dkwl.dkwl_buf, bufsize);
                   1800:                        if (*dkw == NULL)
                   1801:                                return -3;
                   1802:                        dkwl.dkwl_buf = *dkw;
                   1803:                        dkwl.dkwl_bufsize = bufsize;
                   1804:                }
                   1805:        }
                   1806:
1.5       martin   1807:        if (dkwl.dkwl_nwedges > 0 && *dkw != NULL)
1.2       martin   1808:                qsort(*dkw, dkwl.dkwl_nwedges, sizeof(**dkw), get_dkwedges_sort);
                   1809:
                   1810:        close(fd);
                   1811:        return dkwl.dkwl_nwedges;
                   1812: }

CVSweb <webmaster@jp.NetBSD.org>