1*d7f55badSmartin /* $NetBSD: disks.c,v 1.51 2019/08/20 06:38:17 martin Exp $ */ 250dbef1aSdholland 350dbef1aSdholland /* 450dbef1aSdholland * Copyright 1997 Piermont Information Systems Inc. 550dbef1aSdholland * All rights reserved. 650dbef1aSdholland * 750dbef1aSdholland * Written by Philip A. Nelson for Piermont Information Systems Inc. 850dbef1aSdholland * 950dbef1aSdholland * Redistribution and use in source and binary forms, with or without 1050dbef1aSdholland * modification, are permitted provided that the following conditions 1150dbef1aSdholland * are met: 1250dbef1aSdholland * 1. Redistributions of source code must retain the above copyright 1350dbef1aSdholland * notice, this list of conditions and the following disclaimer. 1450dbef1aSdholland * 2. Redistributions in binary form must reproduce the above copyright 1550dbef1aSdholland * notice, this list of conditions and the following disclaimer in the 1650dbef1aSdholland * documentation and/or other materials provided with the distribution. 1750dbef1aSdholland * 3. The name of Piermont Information Systems Inc. may not be used to endorse 1850dbef1aSdholland * or promote products derived from this software without specific prior 1950dbef1aSdholland * written permission. 2050dbef1aSdholland * 2150dbef1aSdholland * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 2250dbef1aSdholland * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2350dbef1aSdholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2450dbef1aSdholland * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 2550dbef1aSdholland * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2650dbef1aSdholland * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2750dbef1aSdholland * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2850dbef1aSdholland * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2950dbef1aSdholland * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3050dbef1aSdholland * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3150dbef1aSdholland * THE POSSIBILITY OF SUCH DAMAGE. 3250dbef1aSdholland * 3350dbef1aSdholland */ 3450dbef1aSdholland 3550dbef1aSdholland /* disks.c -- routines to deal with finding disks and labeling disks. */ 3650dbef1aSdholland 3750dbef1aSdholland 384103857bSmartin #include <assert.h> 3950dbef1aSdholland #include <errno.h> 407a391039Smartin #include <inttypes.h> 4150dbef1aSdholland #include <stdio.h> 4250dbef1aSdholland #include <stdlib.h> 4350dbef1aSdholland #include <unistd.h> 4450dbef1aSdholland #include <fcntl.h> 454bb5c537Smartin #include <fnmatch.h> 4650dbef1aSdholland #include <util.h> 474b2364d9Smartin #include <uuid.h> 484103857bSmartin #include <paths.h> 49a7267d53Smartin #include <fstab.h> 5050dbef1aSdholland 5150dbef1aSdholland #include <sys/param.h> 5250dbef1aSdholland #include <sys/sysctl.h> 5350dbef1aSdholland #include <sys/swap.h> 544103857bSmartin #include <sys/disklabel_gpt.h> 5550dbef1aSdholland #include <ufs/ufs/dinode.h> 5650dbef1aSdholland #include <ufs/ffs/fs.h> 5750dbef1aSdholland 5850dbef1aSdholland #include <dev/scsipi/scsipi_all.h> 5950dbef1aSdholland #include <sys/scsiio.h> 6050dbef1aSdholland 6150dbef1aSdholland #include <dev/ata/atareg.h> 6250dbef1aSdholland #include <sys/ataio.h> 6350dbef1aSdholland 6450dbef1aSdholland #include "defs.h" 6550dbef1aSdholland #include "md.h" 6650dbef1aSdholland #include "msg_defs.h" 6750dbef1aSdholland #include "menu_defs.h" 6850dbef1aSdholland #include "txtwalk.h" 6950dbef1aSdholland 70d396d9d8Smartin /* #define DEBUG_VERBOSE 1 */ 714103857bSmartin 7250dbef1aSdholland /* Disk descriptions */ 7350dbef1aSdholland struct disk_desc { 7450dbef1aSdholland char dd_name[SSTRSIZE]; 7537649e40Smrg char dd_descr[256]; 762575b4dcSmartin bool dd_no_mbr, dd_no_part; 7750dbef1aSdholland uint dd_cyl; 7850dbef1aSdholland uint dd_head; 7950dbef1aSdholland uint dd_sec; 8050dbef1aSdholland uint dd_secsize; 814103857bSmartin daddr_t dd_totsec; 824b2364d9Smartin }; 834b2364d9Smartin 84a7267d53Smartin #define NAME_PREFIX "NAME=" 85a7267d53Smartin static const char name_prefix[] = NAME_PREFIX; 86a7267d53Smartin 87a7267d53Smartin /* things we could have as /sbin/newfs_* and /sbin/fsck_* */ 88a7267d53Smartin static const char *extern_fs_with_chk[] = { 89a7267d53Smartin "ext2fs", "lfs", "msdos", "v7fs" 90a7267d53Smartin }; 91a7267d53Smartin 92a7267d53Smartin /* things we could have as /sbin/newfs_* but not /sbin/fsck_* */ 93a7267d53Smartin static const char *extern_fs_newfs_only[] = { 94a7267d53Smartin "sysvbfs", "udf" 95a7267d53Smartin }; 966de47033Smartin 9750dbef1aSdholland /* Local prototypes */ 98a7267d53Smartin static int found_fs(struct data *, size_t, const struct lookfor*); 99a7267d53Smartin static int found_fs_nocheck(struct data *, size_t, const struct lookfor*); 1004103857bSmartin static int fsck_preen(const char *, const char *, bool silent); 1014103857bSmartin static void fixsb(const char *, const char *); 10250dbef1aSdholland 10350dbef1aSdholland 10450dbef1aSdholland static bool tmpfs_on_var_shm(void); 10550dbef1aSdholland 10650dbef1aSdholland const char * 1074103857bSmartin getfslabelname(uint f, uint f_version) 10850dbef1aSdholland { 1094103857bSmartin if (f == FS_TMPFS) 1104103857bSmartin return "tmpfs"; 1114103857bSmartin else if (f == FS_MFS) 1124103857bSmartin return "mfs"; 1134103857bSmartin else if (f == FS_BSDFFS && f_version > 0) 1144103857bSmartin return f_version == 2 ? 1154103857bSmartin msg_string(MSG_fs_type_ffsv2) : msg_string(MSG_fs_type_ffs); 1164103857bSmartin else if (f >= __arraycount(fstypenames) || fstypenames[f] == NULL) 11750dbef1aSdholland return "invalid"; 11850dbef1aSdholland return fstypenames[f]; 11950dbef1aSdholland } 12050dbef1aSdholland 12150dbef1aSdholland /* 12250dbef1aSdholland * Decide wether we want to mount a tmpfs on /var/shm: we do this always 12350dbef1aSdholland * when the machine has more than 16 MB of user memory. On smaller machines, 12450dbef1aSdholland * shm_open() and friends will not perform well anyway. 12550dbef1aSdholland */ 12650dbef1aSdholland static bool 12750dbef1aSdholland tmpfs_on_var_shm() 12850dbef1aSdholland { 12950dbef1aSdholland uint64_t ram; 13050dbef1aSdholland size_t len; 13150dbef1aSdholland 13250dbef1aSdholland len = sizeof(ram); 13350dbef1aSdholland if (sysctlbyname("hw.usermem64", &ram, &len, NULL, 0)) 13450dbef1aSdholland return false; 13550dbef1aSdholland 13672cf5c53Smartin return ram > 16 * MEG; 13750dbef1aSdholland } 13850dbef1aSdholland 13950dbef1aSdholland /* from src/sbin/atactl/atactl.c 14050dbef1aSdholland * extract_string: copy a block of bytes out of ataparams and make 14150dbef1aSdholland * a proper string out of it, truncating trailing spaces and preserving 14250dbef1aSdholland * strict typing. And also, not doing unaligned accesses. 14350dbef1aSdholland */ 14450dbef1aSdholland static void 14550dbef1aSdholland ata_extract_string(char *buf, size_t bufmax, 14650dbef1aSdholland uint8_t *bytes, unsigned numbytes, 14750dbef1aSdholland int needswap) 14850dbef1aSdholland { 14950dbef1aSdholland unsigned i; 15050dbef1aSdholland size_t j; 15150dbef1aSdholland unsigned char ch1, ch2; 15250dbef1aSdholland 15350dbef1aSdholland for (i = 0, j = 0; i < numbytes; i += 2) { 15450dbef1aSdholland ch1 = bytes[i]; 15550dbef1aSdholland ch2 = bytes[i+1]; 15650dbef1aSdholland if (needswap && j < bufmax-1) { 15750dbef1aSdholland buf[j++] = ch2; 15850dbef1aSdholland } 15950dbef1aSdholland if (j < bufmax-1) { 16050dbef1aSdholland buf[j++] = ch1; 16150dbef1aSdholland } 16250dbef1aSdholland if (!needswap && j < bufmax-1) { 16350dbef1aSdholland buf[j++] = ch2; 16450dbef1aSdholland } 16550dbef1aSdholland } 16650dbef1aSdholland while (j > 0 && buf[j-1] == ' ') { 16750dbef1aSdholland j--; 16850dbef1aSdholland } 16950dbef1aSdholland buf[j] = '\0'; 17050dbef1aSdholland } 17150dbef1aSdholland 17250dbef1aSdholland /* 17350dbef1aSdholland * from src/sbin/scsictl/scsi_subr.c 17450dbef1aSdholland */ 17550dbef1aSdholland #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377') 17650dbef1aSdholland 17750dbef1aSdholland static void 17850dbef1aSdholland scsi_strvis(char *sdst, size_t dlen, const char *ssrc, size_t slen) 17950dbef1aSdholland { 18050dbef1aSdholland u_char *dst = (u_char *)sdst; 18150dbef1aSdholland const u_char *src = (const u_char *)ssrc; 18250dbef1aSdholland 18350dbef1aSdholland /* Trim leading and trailing blanks and NULs. */ 18450dbef1aSdholland while (slen > 0 && STRVIS_ISWHITE(src[0])) 18550dbef1aSdholland ++src, --slen; 18650dbef1aSdholland while (slen > 0 && STRVIS_ISWHITE(src[slen - 1])) 18750dbef1aSdholland --slen; 18850dbef1aSdholland 18950dbef1aSdholland while (slen > 0) { 19050dbef1aSdholland if (*src < 0x20 || *src >= 0x80) { 19150dbef1aSdholland /* non-printable characters */ 19250dbef1aSdholland dlen -= 4; 19350dbef1aSdholland if (dlen < 1) 19450dbef1aSdholland break; 19550dbef1aSdholland *dst++ = '\\'; 19650dbef1aSdholland *dst++ = ((*src & 0300) >> 6) + '0'; 19750dbef1aSdholland *dst++ = ((*src & 0070) >> 3) + '0'; 19850dbef1aSdholland *dst++ = ((*src & 0007) >> 0) + '0'; 19950dbef1aSdholland } else if (*src == '\\') { 20050dbef1aSdholland /* quote characters */ 20150dbef1aSdholland dlen -= 2; 20250dbef1aSdholland if (dlen < 1) 20350dbef1aSdholland break; 20450dbef1aSdholland *dst++ = '\\'; 20550dbef1aSdholland *dst++ = '\\'; 20650dbef1aSdholland } else { 20750dbef1aSdholland /* normal characters */ 20850dbef1aSdholland if (--dlen < 1) 20950dbef1aSdholland break; 21050dbef1aSdholland *dst++ = *src; 21150dbef1aSdholland } 21250dbef1aSdholland ++src, --slen; 21350dbef1aSdholland } 21450dbef1aSdholland 21550dbef1aSdholland *dst++ = 0; 21650dbef1aSdholland } 21750dbef1aSdholland 21850dbef1aSdholland 21950dbef1aSdholland static int 22072ea5dbaSchristos get_descr_scsi(struct disk_desc *dd) 22150dbef1aSdholland { 22250dbef1aSdholland struct scsipi_inquiry_data inqbuf; 22350dbef1aSdholland struct scsipi_inquiry cmd; 22450dbef1aSdholland scsireq_t req; 22550dbef1aSdholland /* x4 in case every character is escaped, +1 for NUL. */ 22650dbef1aSdholland char vendor[(sizeof(inqbuf.vendor) * 4) + 1], 22750dbef1aSdholland product[(sizeof(inqbuf.product) * 4) + 1], 22850dbef1aSdholland revision[(sizeof(inqbuf.revision) * 4) + 1]; 22950dbef1aSdholland char size[5]; 23050dbef1aSdholland 23150dbef1aSdholland memset(&inqbuf, 0, sizeof(inqbuf)); 23250dbef1aSdholland memset(&cmd, 0, sizeof(cmd)); 23350dbef1aSdholland memset(&req, 0, sizeof(req)); 23450dbef1aSdholland 23550dbef1aSdholland cmd.opcode = INQUIRY; 23650dbef1aSdholland cmd.length = sizeof(inqbuf); 23750dbef1aSdholland memcpy(req.cmd, &cmd, sizeof(cmd)); 23850dbef1aSdholland req.cmdlen = sizeof(cmd); 23950dbef1aSdholland req.databuf = &inqbuf; 24050dbef1aSdholland req.datalen = sizeof(inqbuf); 24150dbef1aSdholland req.timeout = 10000; 24250dbef1aSdholland req.flags = SCCMD_READ; 24350dbef1aSdholland req.senselen = SENSEBUFLEN; 24450dbef1aSdholland 24572ea5dbaSchristos if (!disk_ioctl(dd->dd_name, SCIOCCOMMAND, &req) 24672ea5dbaSchristos || req.retsts != SCCMD_OK) 24750dbef1aSdholland return 0; 24850dbef1aSdholland 24950dbef1aSdholland scsi_strvis(vendor, sizeof(vendor), inqbuf.vendor, 25050dbef1aSdholland sizeof(inqbuf.vendor)); 25150dbef1aSdholland scsi_strvis(product, sizeof(product), inqbuf.product, 25250dbef1aSdholland sizeof(inqbuf.product)); 25350dbef1aSdholland scsi_strvis(revision, sizeof(revision), inqbuf.revision, 25450dbef1aSdholland sizeof(inqbuf.revision)); 25550dbef1aSdholland 25650dbef1aSdholland humanize_number(size, sizeof(size), 25750dbef1aSdholland (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec, 25850dbef1aSdholland "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 25950dbef1aSdholland 26050dbef1aSdholland snprintf(dd->dd_descr, sizeof(dd->dd_descr), 26150dbef1aSdholland "%s (%s, %s %s)", 26250dbef1aSdholland dd->dd_name, size, vendor, product); 26350dbef1aSdholland 26450dbef1aSdholland return 1; 26550dbef1aSdholland } 26650dbef1aSdholland 26750dbef1aSdholland static int 26872ea5dbaSchristos get_descr_ata(struct disk_desc *dd) 26950dbef1aSdholland { 27050dbef1aSdholland struct atareq req; 27150dbef1aSdholland static union { 27250dbef1aSdholland unsigned char inbuf[DEV_BSIZE]; 27350dbef1aSdholland struct ataparams inqbuf; 27450dbef1aSdholland } inbuf; 27550dbef1aSdholland struct ataparams *inqbuf = &inbuf.inqbuf; 27650dbef1aSdholland char model[sizeof(inqbuf->atap_model)+1]; 27750dbef1aSdholland char size[5]; 27872ea5dbaSchristos int needswap = 0; 27950dbef1aSdholland 28050dbef1aSdholland memset(&inbuf, 0, sizeof(inbuf)); 28150dbef1aSdholland memset(&req, 0, sizeof(req)); 28250dbef1aSdholland 28350dbef1aSdholland req.flags = ATACMD_READ; 28450dbef1aSdholland req.command = WDCC_IDENTIFY; 28550dbef1aSdholland req.databuf = (void *)&inbuf; 28650dbef1aSdholland req.datalen = sizeof(inbuf); 28750dbef1aSdholland req.timeout = 1000; 28850dbef1aSdholland 28972ea5dbaSchristos if (!disk_ioctl(dd->dd_name, ATAIOCCOMMAND, &req) 29072ea5dbaSchristos || req.retsts != ATACMD_OK) 29150dbef1aSdholland return 0; 29250dbef1aSdholland 29350dbef1aSdholland #if BYTE_ORDER == LITTLE_ENDIAN 29450dbef1aSdholland /* 29550dbef1aSdholland * On little endian machines, we need to shuffle the string 29650dbef1aSdholland * byte order. However, we don't have to do this for NEC or 29750dbef1aSdholland * Mitsumi ATAPI devices 29850dbef1aSdholland */ 29950dbef1aSdholland 30050dbef1aSdholland if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC && 30150dbef1aSdholland (inqbuf->atap_config & WDC_CFG_ATAPI) && 30250dbef1aSdholland ((inqbuf->atap_model[0] == 'N' && 30350dbef1aSdholland inqbuf->atap_model[1] == 'E') || 30450dbef1aSdholland (inqbuf->atap_model[0] == 'F' && 30550dbef1aSdholland inqbuf->atap_model[1] == 'X')))) { 30650dbef1aSdholland needswap = 1; 30750dbef1aSdholland } 30850dbef1aSdholland #endif 30950dbef1aSdholland 31050dbef1aSdholland ata_extract_string(model, sizeof(model), 31150dbef1aSdholland inqbuf->atap_model, sizeof(inqbuf->atap_model), needswap); 31250dbef1aSdholland humanize_number(size, sizeof(size), 31350dbef1aSdholland (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec, 31450dbef1aSdholland "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 31550dbef1aSdholland 31650dbef1aSdholland snprintf(dd->dd_descr, sizeof(dd->dd_descr), "%s (%s, %s)", 31750dbef1aSdholland dd->dd_name, size, model); 31850dbef1aSdholland 31950dbef1aSdholland return 1; 32050dbef1aSdholland } 32150dbef1aSdholland 32250dbef1aSdholland static void 32350dbef1aSdholland get_descr(struct disk_desc *dd) 32450dbef1aSdholland { 32572ea5dbaSchristos char size[5]; 32650dbef1aSdholland dd->dd_descr[0] = '\0'; 32750dbef1aSdholland 32850dbef1aSdholland /* try ATA */ 32972ea5dbaSchristos if (get_descr_ata(dd)) 33050dbef1aSdholland goto done; 33150dbef1aSdholland /* try SCSI */ 33272ea5dbaSchristos if (get_descr_scsi(dd)) 33350dbef1aSdholland goto done; 3344103857bSmartin 3354103857bSmartin /* XXX: identify for ld @ NVME or microSD */ 3364103857bSmartin 3374b2364d9Smartin /* XXX: get description from raid, cgd, vnd... */ 33872ea5dbaSchristos done: 3394103857bSmartin /* punt, just give some generic info */ 3404103857bSmartin humanize_number(size, sizeof(size), 3414103857bSmartin (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec, 3424103857bSmartin "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 3434103857bSmartin 3444103857bSmartin snprintf(dd->dd_descr, sizeof(dd->dd_descr), 3454103857bSmartin "%s (%s)", dd->dd_name, size); 34650dbef1aSdholland } 34750dbef1aSdholland 348a48ed55eSmartin /* 349a48ed55eSmartin * State for helper callback for get_default_cdrom 350a48ed55eSmartin */ 351a48ed55eSmartin struct default_cdrom_data { 352a48ed55eSmartin char *device; 353a48ed55eSmartin size_t max_len; 354a48ed55eSmartin bool found; 355a48ed55eSmartin }; 356a48ed55eSmartin 357a48ed55eSmartin /* 358a48ed55eSmartin * Helper function for get_default_cdrom, gets passed a device 359a48ed55eSmartin * name and a void pointer to default_cdrom_data. 360a48ed55eSmartin */ 361a48ed55eSmartin static bool 362a48ed55eSmartin get_default_cdrom_helper(void *state, const char *dev) 363a48ed55eSmartin { 364a48ed55eSmartin struct default_cdrom_data *data = state; 365a48ed55eSmartin 36657cf8237Smartin if (!is_cdrom_device(dev, false)) 3671c2e5b02Smartin return true; 3681c2e5b02Smartin 369a48ed55eSmartin strlcpy(data->device, dev, data->max_len); 3701c2e5b02Smartin strlcat(data->device, "a", data->max_len); /* default to partition a */ 371a48ed55eSmartin data->found = true; 372a48ed55eSmartin 373a48ed55eSmartin return false; /* one is enough, stop iteration */ 374a48ed55eSmartin } 375a48ed55eSmartin 376a48ed55eSmartin /* 377a48ed55eSmartin * Set the argument to the name of the first CD devices actually 378a48ed55eSmartin * available, leave it unmodified otherwise. 379a48ed55eSmartin * Return true if a device has been found. 38050dbef1aSdholland */ 3813b44a3d7Smartin bool 3823b44a3d7Smartin get_default_cdrom(char *cd, size_t max_len) 38350dbef1aSdholland { 384a48ed55eSmartin struct default_cdrom_data state; 38550dbef1aSdholland 386a48ed55eSmartin state.device = cd; 387a48ed55eSmartin state.max_len = max_len; 388a48ed55eSmartin state.found = false; 38950dbef1aSdholland 390a48ed55eSmartin if (enumerate_disks(&state, get_default_cdrom_helper)) 391a48ed55eSmartin return state.found; 392a48ed55eSmartin 393a48ed55eSmartin return false; 39450dbef1aSdholland } 39550dbef1aSdholland 3964103857bSmartin static bool 3972575b4dcSmartin get_wedge_descr(struct disk_desc *dd) 3982575b4dcSmartin { 3992575b4dcSmartin struct dkwedge_info dkw; 4002575b4dcSmartin 40172ea5dbaSchristos if (!get_wedge_info(dd->dd_name, &dkw)) 4024103857bSmartin return false; 4032575b4dcSmartin 40472ea5dbaSchristos snprintf(dd->dd_descr, sizeof(dd->dd_descr), "%s (%s@%s)", 4052575b4dcSmartin dkw.dkw_wname, dkw.dkw_devname, dkw.dkw_parent); 40672ea5dbaSchristos return true; 4072575b4dcSmartin } 4082575b4dcSmartin 4092575b4dcSmartin static bool 4102575b4dcSmartin get_name_and_parent(const char *dev, char *name, char *parent) 4112575b4dcSmartin { 4122575b4dcSmartin struct dkwedge_info dkw; 4132575b4dcSmartin 41472ea5dbaSchristos if (!get_wedge_info(dev, &dkw)) 4152575b4dcSmartin return false; 4162575b4dcSmartin strcpy(name, (const char *)dkw.dkw_wname); 4172575b4dcSmartin strcpy(parent, dkw.dkw_parent); 41872ea5dbaSchristos return true; 4192575b4dcSmartin } 4202575b4dcSmartin 4212575b4dcSmartin static bool 4222575b4dcSmartin find_swap_part_on(const char *dev, char *swap_name) 4232575b4dcSmartin { 4242575b4dcSmartin struct dkwedge_list dkwl; 42572ea5dbaSchristos struct dkwedge_info *dkw; 4262575b4dcSmartin u_int i; 4272575b4dcSmartin bool res = false; 4282575b4dcSmartin 42972ea5dbaSchristos if (!get_wedge_list(dev, &dkwl)) 4302575b4dcSmartin return false; 4312575b4dcSmartin 43272ea5dbaSchristos dkw = dkwl.dkwl_buf; 4332575b4dcSmartin for (i = 0; i < dkwl.dkwl_nwedges; i++) { 4342575b4dcSmartin res = strcmp(dkw[i].dkw_ptype, DKW_PTYPE_SWAP) == 0; 4352575b4dcSmartin if (res) { 4362575b4dcSmartin strcpy(swap_name, (const char*)dkw[i].dkw_wname); 4372575b4dcSmartin break; 4382575b4dcSmartin } 4392575b4dcSmartin } 44072ea5dbaSchristos free(dkwl.dkwl_buf); 4412575b4dcSmartin 4422575b4dcSmartin return res; 4432575b4dcSmartin } 4442575b4dcSmartin 4452575b4dcSmartin static bool 4462575b4dcSmartin is_ffs_wedge(const char *dev) 4472575b4dcSmartin { 4482575b4dcSmartin struct dkwedge_info dkw; 4492575b4dcSmartin 45072ea5dbaSchristos if (!get_wedge_info(dev, &dkw)) 4512575b4dcSmartin return false; 4522575b4dcSmartin 45372ea5dbaSchristos return strcmp(dkw.dkw_ptype, DKW_PTYPE_FFS) == 0; 4542575b4dcSmartin } 4552575b4dcSmartin 4563b44a3d7Smartin /* 4573b44a3d7Smartin * Does this device match an entry in our default CDROM device list? 45857cf8237Smartin * If looking for install targets, we also flag floopy devices. 4593b44a3d7Smartin */ 4601c2e5b02Smartin bool 46157cf8237Smartin is_cdrom_device(const char *dev, bool as_target) 4623b44a3d7Smartin { 46357cf8237Smartin static const char *target_devices[] = { 4648b5066c4Smartin #ifdef CD_NAMES 4658b5066c4Smartin CD_NAMES 4668b5066c4Smartin #endif 4678b5066c4Smartin #if defined(CD_NAMES) && defined(FLOPPY_NAMES) 4688b5066c4Smartin , 4698b5066c4Smartin #endif 4708b5066c4Smartin #ifdef FLOPPY_NAMES 4718b5066c4Smartin FLOPPY_NAMES 4728b5066c4Smartin #endif 4738b5066c4Smartin #if defined(CD_NAMES) || defined(FLOPPY_NAMES) 4748b5066c4Smartin , 4758b5066c4Smartin #endif 4768b5066c4Smartin 0 4778b5066c4Smartin }; 47857cf8237Smartin static const char *src_devices[] = { 47957cf8237Smartin #ifdef CD_NAMES 48057cf8237Smartin CD_NAMES , 48157cf8237Smartin #endif 48257cf8237Smartin 0 48357cf8237Smartin }; 4843b44a3d7Smartin 48557cf8237Smartin for (const char **dev_pat = as_target ? target_devices : src_devices; 48657cf8237Smartin *dev_pat; dev_pat++) 4874bb5c537Smartin if (fnmatch(*dev_pat, dev, 0) == 0) 488e80b64deSmartin return true; 4893b44a3d7Smartin 4903b44a3d7Smartin return false; 4913b44a3d7Smartin } 4923b44a3d7Smartin 493c4cf3d8dSmartin /* does this device match any entry in the driver list? */ 494c4cf3d8dSmartin static bool 495c4cf3d8dSmartin dev_in_list(const char *dev, const char **list) 496c4cf3d8dSmartin { 497c4cf3d8dSmartin 498c4cf3d8dSmartin for ( ; *list; list++) { 499c4cf3d8dSmartin 500c4cf3d8dSmartin size_t len = strlen(*list); 501c4cf3d8dSmartin 502c4cf3d8dSmartin /* start of name matches? */ 503c4cf3d8dSmartin if (strncmp(dev, *list, len) == 0) { 504c4cf3d8dSmartin char *endp; 505c4cf3d8dSmartin int e; 506c4cf3d8dSmartin 507c4cf3d8dSmartin /* remainder of name is a decimal number? */ 508c4cf3d8dSmartin strtou(dev+len, &endp, 10, 0, INT_MAX, &e); 509c4cf3d8dSmartin if (endp && *endp == 0 && e == 0) 510c4cf3d8dSmartin return true; 511c4cf3d8dSmartin } 512c4cf3d8dSmartin } 513c4cf3d8dSmartin 514c4cf3d8dSmartin return false; 515c4cf3d8dSmartin } 516c4cf3d8dSmartin 517c4cf3d8dSmartin bool 518c4cf3d8dSmartin is_bootable_device(const char *dev) 519c4cf3d8dSmartin { 520c4cf3d8dSmartin static const char *non_bootable_devs[] = { 521c4cf3d8dSmartin "raid", /* bootcode lives outside of raid */ 522c4cf3d8dSmartin "xbd", /* xen virtual device, can not boot from that */ 523c4cf3d8dSmartin NULL 524c4cf3d8dSmartin }; 525c4cf3d8dSmartin 526c4cf3d8dSmartin return !dev_in_list(dev, non_bootable_devs); 527c4cf3d8dSmartin } 528c4cf3d8dSmartin 529c4cf3d8dSmartin bool 530c4cf3d8dSmartin is_partitionable_device(const char *dev) 531c4cf3d8dSmartin { 532c4cf3d8dSmartin static const char *non_partitionable_devs[] = { 533d4a37f7cSmsaitoh "dk", /* this is already a partitioned slice */ 534c4cf3d8dSmartin NULL 535c4cf3d8dSmartin }; 536c4cf3d8dSmartin 537c4cf3d8dSmartin return !dev_in_list(dev, non_partitionable_devs); 538c4cf3d8dSmartin } 539c4cf3d8dSmartin 5403b44a3d7Smartin /* 5413b44a3d7Smartin * Multi-purpose helper function: 542a48ed55eSmartin * iterate all known disks, invoke a callback for each. 543a48ed55eSmartin * Stop iteration when the callback returns false. 544a48ed55eSmartin * Return true when iteration actually happend, false on error. 5453b44a3d7Smartin */ 5461c2e5b02Smartin bool 547a48ed55eSmartin enumerate_disks(void *state, bool (*func)(void *state, const char *dev)) 54850dbef1aSdholland { 5497a391039Smartin static const int mib[] = { CTL_HW, HW_DISKNAMES }; 5507a391039Smartin static const unsigned int miblen = __arraycount(mib); 5517a391039Smartin const char *xd; 5527a391039Smartin char *disk_names; 553a48ed55eSmartin size_t len; 55450dbef1aSdholland 5557a391039Smartin if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) 556a48ed55eSmartin return false; 557a48ed55eSmartin 5587a391039Smartin disk_names = malloc(len); 5597a391039Smartin if (disk_names == NULL) 560a48ed55eSmartin return false; 5617a391039Smartin 5627a391039Smartin if (sysctl(mib, miblen, disk_names, &len, NULL, 0) == -1) { 5637a391039Smartin free(disk_names); 564a48ed55eSmartin return false; 5657a391039Smartin } 5667a391039Smartin 5677a391039Smartin for (xd = strtok(disk_names, " "); xd != NULL; xd = strtok(NULL, " ")) { 568a48ed55eSmartin if (!(*func)(state, xd)) 569a48ed55eSmartin break; 570a48ed55eSmartin } 571a48ed55eSmartin free(disk_names); 572a48ed55eSmartin 573a48ed55eSmartin return true; 574a48ed55eSmartin } 575a48ed55eSmartin 576a48ed55eSmartin /* 577a48ed55eSmartin * Helper state for get_disks 578a48ed55eSmartin */ 579a48ed55eSmartin struct get_disks_state { 580a48ed55eSmartin int numdisks; 581a48ed55eSmartin struct disk_desc *dd; 582a48ed55eSmartin bool with_non_partitionable; 583a48ed55eSmartin }; 584a48ed55eSmartin 585a48ed55eSmartin /* 586a48ed55eSmartin * Helper function for get_disks enumartion 587a48ed55eSmartin */ 588a48ed55eSmartin static bool 589a48ed55eSmartin get_disks_helper(void *arg, const char *dev) 590a48ed55eSmartin { 591a48ed55eSmartin struct get_disks_state *state = arg; 5924103857bSmartin struct disk_geom geo; 593a48ed55eSmartin 5943b44a3d7Smartin /* is this a CD device? */ 59557cf8237Smartin if (is_cdrom_device(dev, true)) 596a48ed55eSmartin return true; 5973b44a3d7Smartin 598c4cf3d8dSmartin memset(state->dd, 0, sizeof(*state->dd)); 599a48ed55eSmartin strlcpy(state->dd->dd_name, dev, sizeof state->dd->dd_name - 2); 600c4cf3d8dSmartin state->dd->dd_no_mbr = !is_bootable_device(dev); 601c4cf3d8dSmartin state->dd->dd_no_part = !is_partitionable_device(dev); 6027a391039Smartin 603a48ed55eSmartin if (state->dd->dd_no_part && !state->with_non_partitionable) 604a48ed55eSmartin return true; 60550dbef1aSdholland 6064103857bSmartin if (!get_disk_geom(state->dd->dd_name, &geo)) { 60750dbef1aSdholland if (errno == ENOENT) 608a48ed55eSmartin return true; 609a48ed55eSmartin if (errno != ENOTTY || !state->dd->dd_no_part) 6102575b4dcSmartin /* 6112575b4dcSmartin * Allow plain partitions, 6122575b4dcSmartin * like already existing wedges 6132575b4dcSmartin * (like dk0) if marked as 6142575b4dcSmartin * non-partitioning device. 6152575b4dcSmartin * For all other cases, continue 6162575b4dcSmartin * with the next disk. 6172575b4dcSmartin */ 618a48ed55eSmartin return true; 619a48ed55eSmartin if (!is_ffs_wedge(state->dd->dd_name)) 620a48ed55eSmartin return true; 62150dbef1aSdholland } 62250dbef1aSdholland 62350dbef1aSdholland /* 62450dbef1aSdholland * Exclude a disk mounted as root partition, 62550dbef1aSdholland * in case of install-image on a USB memstick. 62650dbef1aSdholland */ 6275864e121Smartin if (is_active_rootpart(state->dd->dd_name, 6285864e121Smartin state->dd->dd_no_part ? -1 : 0)) 629a48ed55eSmartin return true; 63050dbef1aSdholland 6314103857bSmartin state->dd->dd_cyl = geo.dg_ncylinders; 6324103857bSmartin state->dd->dd_head = geo.dg_ntracks; 6334103857bSmartin state->dd->dd_sec = geo.dg_nsectors; 6344103857bSmartin state->dd->dd_secsize = geo.dg_secsize; 6354103857bSmartin state->dd->dd_totsec = geo.dg_secperunit; 6364103857bSmartin 6374103857bSmartin if (!state->dd->dd_no_part || !get_wedge_descr(state->dd)) 638a48ed55eSmartin get_descr(state->dd); 639a48ed55eSmartin state->dd++; 640a48ed55eSmartin state->numdisks++; 641a48ed55eSmartin if (state->numdisks == MAX_DISKS) 642a48ed55eSmartin return false; 643a48ed55eSmartin 644a48ed55eSmartin return true; 64550dbef1aSdholland } 646a48ed55eSmartin 647a48ed55eSmartin /* 648a48ed55eSmartin * Get all disk devices that are not CDs. 649a48ed55eSmartin * Optionally leave out those that can not be partitioned further. 650a48ed55eSmartin */ 651a48ed55eSmartin static int 652a48ed55eSmartin get_disks(struct disk_desc *dd, bool with_non_partitionable) 653a48ed55eSmartin { 654a48ed55eSmartin struct get_disks_state state; 655a48ed55eSmartin 656a48ed55eSmartin /* initialize */ 657a48ed55eSmartin state.numdisks = 0; 658a48ed55eSmartin state.dd = dd; 659a48ed55eSmartin state.with_non_partitionable = with_non_partitionable; 660a48ed55eSmartin 661a48ed55eSmartin if (enumerate_disks(&state, get_disks_helper)) 662a48ed55eSmartin return state.numdisks; 663a48ed55eSmartin 664a48ed55eSmartin return 0; 66550dbef1aSdholland } 66650dbef1aSdholland 6674103857bSmartin #ifdef DEBUG_VERBOSE 6684103857bSmartin static void 6694103857bSmartin dump_parts(const struct disk_partitions *parts) 6704103857bSmartin { 6714103857bSmartin fprintf(stderr, "%s partitions on %s:\n", 6724103857bSmartin MSG_XLAT(parts->pscheme->short_name), parts->disk); 6734103857bSmartin 6744103857bSmartin for (size_t p = 0; p < parts->num_part; p++) { 6754103857bSmartin struct disk_part_info info; 6764103857bSmartin 6774103857bSmartin if (parts->pscheme->get_part_info( 6784103857bSmartin parts, p, &info)) { 6794103857bSmartin fprintf(stderr, " #%zu: start: %" PRIu64 " " 6804103857bSmartin "size: %" PRIu64 ", flags: %x\n", 6814103857bSmartin p, info.start, info.size, 6824103857bSmartin info.flags); 6834103857bSmartin if (info.nat_type) 6844103857bSmartin fprintf(stderr, "\ttype: %s\n", 6854103857bSmartin info.nat_type->description); 6864103857bSmartin } else { 6874103857bSmartin fprintf(stderr, "failed to get info " 6884103857bSmartin "for partition #%zu\n", p); 6894103857bSmartin } 6904103857bSmartin } 6914103857bSmartin fprintf(stderr, "%" PRIu64 " sectors free, disk size %" PRIu64 6924103857bSmartin " sectors, %zu partitions used\n", parts->free_space, 6934103857bSmartin parts->disk_size, parts->num_part); 6944103857bSmartin } 6954103857bSmartin #endif 6964103857bSmartin 6974103857bSmartin static bool 6984103857bSmartin delete_scheme(struct pm_devs *p) 6994103857bSmartin { 7004103857bSmartin 7014103857bSmartin if (!ask_noyes(MSG_removepartswarn)) 7024103857bSmartin return false; 7034103857bSmartin 7044103857bSmartin p->parts->pscheme->free(p->parts); 7054103857bSmartin p->parts = NULL; 7064103857bSmartin return true; 7074103857bSmartin } 7084103857bSmartin 7094103857bSmartin 7104103857bSmartin static void 7114103857bSmartin convert_copy(struct disk_partitions *old_parts, 7124103857bSmartin struct disk_partitions *new_parts) 7134103857bSmartin { 7144103857bSmartin struct disk_part_info oinfo, ninfo; 7154103857bSmartin part_id i; 7164103857bSmartin 7174103857bSmartin for (i = 0; i < old_parts->num_part; i++) { 7184103857bSmartin if (!old_parts->pscheme->get_part_info(old_parts, i, &oinfo)) 7194103857bSmartin continue; 7204103857bSmartin 7214103857bSmartin if (oinfo.flags & PTI_PSCHEME_INTERNAL) 7224103857bSmartin continue; 7234103857bSmartin 7244103857bSmartin if (oinfo.flags & PTI_SEC_CONTAINER) { 7254103857bSmartin if (old_parts->pscheme->secondary_partitions) { 7264103857bSmartin struct disk_partitions *sec_part = 7274103857bSmartin old_parts->pscheme-> 7284103857bSmartin secondary_partitions( 72983478358Smartin old_parts, oinfo.start, false); 7304103857bSmartin if (sec_part) 7314103857bSmartin convert_copy(sec_part, new_parts); 7324103857bSmartin } 7334103857bSmartin continue; 7344103857bSmartin } 7354103857bSmartin 7364103857bSmartin if (!new_parts->pscheme->adapt_foreign_part_info(new_parts, 7374103857bSmartin &oinfo, &ninfo)) 7384103857bSmartin continue; 7394103857bSmartin new_parts->pscheme->add_partition(new_parts, &ninfo, NULL); 7404103857bSmartin } 7414103857bSmartin } 7424103857bSmartin 7434103857bSmartin bool 7444103857bSmartin convert_scheme(struct pm_devs *p, bool is_boot_drive, const char **err_msg) 7454103857bSmartin { 7464103857bSmartin struct disk_partitions *old_parts, *new_parts; 7474103857bSmartin const struct disk_partitioning_scheme *new_scheme; 7484103857bSmartin 7494103857bSmartin *err_msg = NULL; 7504103857bSmartin 7514103857bSmartin old_parts = p->parts; 7524103857bSmartin new_scheme = select_part_scheme(p, old_parts->pscheme, 7534103857bSmartin false, MSG_select_other_partscheme); 7544103857bSmartin 7554103857bSmartin if (new_scheme == NULL) 7564103857bSmartin return false; 7574103857bSmartin 7584103857bSmartin new_parts = new_scheme->create_new_for_disk(p->diskdev, 7594103857bSmartin 0, p->dlsize, p->dlsize, is_boot_drive); 7604103857bSmartin if (new_parts == NULL) 7614103857bSmartin return false; 7624103857bSmartin 7634103857bSmartin convert_copy(old_parts, new_parts); 7644103857bSmartin 7654103857bSmartin if (new_parts->num_part == 0) { 7664103857bSmartin /* need to cleanup */ 7674103857bSmartin new_parts->pscheme->free(new_parts); 7684103857bSmartin return false; 7694103857bSmartin } 7704103857bSmartin 7714103857bSmartin old_parts->pscheme->free(old_parts); 7724103857bSmartin p->parts = new_parts; 7734103857bSmartin return true; 7744103857bSmartin } 7754103857bSmartin 776b1fa9754Smartin static struct pm_devs * 777b1fa9754Smartin dummy_whole_system_pm(void) 778b1fa9754Smartin { 779b1fa9754Smartin static struct pm_devs whole_system = { 780b1fa9754Smartin .diskdev = "/", 781b1fa9754Smartin .no_mbr = true, 782b1fa9754Smartin .no_part = true, 783b1fa9754Smartin .cur_system = true, 784b1fa9754Smartin }; 785b1fa9754Smartin static bool init = false; 786b1fa9754Smartin 787b1fa9754Smartin if (!init) { 788b1fa9754Smartin strlcpy(whole_system.diskdev_descr, 789b1fa9754Smartin msg_string(MSG_running_system), 790b1fa9754Smartin sizeof whole_system.diskdev_descr); 791b1fa9754Smartin } 792b1fa9754Smartin 793b1fa9754Smartin return &whole_system; 794b1fa9754Smartin } 795b1fa9754Smartin 79650dbef1aSdholland int 797b1fa9754Smartin find_disks(const char *doingwhat, bool allow_cur_system) 79850dbef1aSdholland { 79950dbef1aSdholland struct disk_desc disks[MAX_DISKS]; 800b1fa9754Smartin /* need two more menu entries: current system + extended partitioning */ 801b1fa9754Smartin menu_ent dsk_menu[__arraycount(disks) + 2]; 80250dbef1aSdholland struct disk_desc *disk; 8032575b4dcSmartin int i = 0, skipped = 0; 8042575b4dcSmartin int already_found, numdisks, selected_disk = -1; 80550dbef1aSdholland int menu_no; 8064103857bSmartin struct pm_devs *pm_i, *pm_last = NULL; 8074103857bSmartin 8084103857bSmartin memset(dsk_menu, 0, sizeof(dsk_menu)); 80950dbef1aSdholland 81050dbef1aSdholland /* Find disks. */ 811a48ed55eSmartin numdisks = get_disks(disks, partman_go <= 0); 81250dbef1aSdholland 81350dbef1aSdholland /* need a redraw here, kernel messages hose everything */ 81450dbef1aSdholland touchwin(stdscr); 81550dbef1aSdholland refresh(); 81650dbef1aSdholland /* Kill typeahead, it won't be what the user had in mind */ 81750dbef1aSdholland fpurge(stdin); 81850dbef1aSdholland 819bbeaff62Sisaki /* 820bbeaff62Sisaki * partman_go: <0 - we want to see menu with extended partitioning 821bbeaff62Sisaki * ==0 - we want to see simple select disk menu 822bbeaff62Sisaki * >0 - we do not want to see any menus, just detect 823bbeaff62Sisaki * all disks 824bbeaff62Sisaki */ 8254b2364d9Smartin if (partman_go <= 0) { 826b1fa9754Smartin if (numdisks == 0 && !allow_cur_system) { 82750dbef1aSdholland /* No disks found! */ 8284103857bSmartin hit_enter_to_continue(MSG_nodisk, NULL); 82950dbef1aSdholland /*endwin();*/ 83050dbef1aSdholland return -1; 83150dbef1aSdholland } else { 832b1fa9754Smartin /* One or more disks found or current system allowed */ 833b1fa9754Smartin i = 0; 834b1fa9754Smartin if (allow_cur_system) { 835b1fa9754Smartin dsk_menu[i].opt_name = MSG_running_system; 836b1fa9754Smartin dsk_menu[i].opt_flags = OPT_EXIT; 837b1fa9754Smartin dsk_menu[i].opt_action = set_menu_select; 838b1fa9754Smartin i++; 839b1fa9754Smartin } 8407edc37a7Smartin for (; i < numdisks+allow_cur_system; i++) { 8412575b4dcSmartin dsk_menu[i].opt_name = 842b1fa9754Smartin disks[i-allow_cur_system].dd_descr; 84350dbef1aSdholland dsk_menu[i].opt_flags = OPT_EXIT; 8444b2364d9Smartin dsk_menu[i].opt_action = set_menu_select; 8454b2364d9Smartin } 8464b2364d9Smartin if (partman_go < 0) { 8474b2364d9Smartin dsk_menu[i].opt_name = MSG_partman; 8484b2364d9Smartin dsk_menu[i].opt_flags = OPT_EXIT; 8494b2364d9Smartin dsk_menu[i].opt_action = set_menu_select; 850b1fa9754Smartin i++; 85150dbef1aSdholland } 85250dbef1aSdholland menu_no = new_menu(MSG_Available_disks, 853b1fa9754Smartin dsk_menu, i, -1, 8542575b4dcSmartin 4, 0, 0, MC_SCROLL, 85550dbef1aSdholland NULL, NULL, NULL, NULL, NULL); 85650dbef1aSdholland if (menu_no == -1) 85750dbef1aSdholland return -1; 85824ecf24eSchristos msg_fmt_display(MSG_ask_disk, "%s", doingwhat); 85950dbef1aSdholland process_menu(menu_no, &selected_disk); 86050dbef1aSdholland free_menu(menu_no); 861b1fa9754Smartin if (allow_cur_system) { 862b1fa9754Smartin if (selected_disk == 0) { 863b1fa9754Smartin pm = dummy_whole_system_pm(); 864b1fa9754Smartin return 1; 865b1fa9754Smartin } else { 866b1fa9754Smartin selected_disk--; 867b1fa9754Smartin } 868b1fa9754Smartin } 86950dbef1aSdholland } 8704b2364d9Smartin if (partman_go < 0 && selected_disk == numdisks) { 8714b2364d9Smartin partman_go = 1; 8724b2364d9Smartin return -2; 8734b2364d9Smartin } else 8744b2364d9Smartin partman_go = 0; 8754b2364d9Smartin if (selected_disk < 0 || selected_disk >= numdisks) 8764b2364d9Smartin return -1; 8774b2364d9Smartin } 87850dbef1aSdholland 8794b2364d9Smartin /* Fill pm struct with device(s) info */ 8804b2364d9Smartin for (i = 0; i < numdisks; i++) { 8814b2364d9Smartin if (! partman_go) 88250dbef1aSdholland disk = disks + selected_disk; 8834b2364d9Smartin else { 8844b2364d9Smartin disk = disks + i; 8854b2364d9Smartin already_found = 0; 8864b2364d9Smartin SLIST_FOREACH(pm_i, &pm_head, l) { 8874b2364d9Smartin pm_last = pm_i; 888e32f4c09Smartin if (strcmp(pm_i->diskdev, disk->dd_name) == 0) { 889e32f4c09Smartin already_found = 1; 8904b2364d9Smartin break; 8914b2364d9Smartin } 8924b2364d9Smartin } 893e32f4c09Smartin if (pm_i != NULL && already_found) { 894e32f4c09Smartin /* 895e32f4c09Smartin * We already added this device, but 896e32f4c09Smartin * partitions might have changed 897e32f4c09Smartin */ 898e32f4c09Smartin if (!pm_i->found) { 899e32f4c09Smartin pm_i->found = true; 900e32f4c09Smartin if (pm_i->parts == NULL) { 901e32f4c09Smartin pm_i->parts = 902e32f4c09Smartin partitions_read_disk( 903e32f4c09Smartin pm_i->diskdev, 904e32f4c09Smartin disk->dd_totsec); 905e32f4c09Smartin } 906e32f4c09Smartin } 9074b2364d9Smartin continue; 9084b2364d9Smartin } 909e32f4c09Smartin } 9104b2364d9Smartin pm = pm_new; 9114b2364d9Smartin pm->found = 1; 9124103857bSmartin pm->ptstart = 0; 9134103857bSmartin pm->ptsize = 0; 9144b2364d9Smartin pm->bootable = 0; 9154b2364d9Smartin strlcpy(pm->diskdev, disk->dd_name, sizeof pm->diskdev); 9164b2364d9Smartin strlcpy(pm->diskdev_descr, disk->dd_descr, sizeof pm->diskdev_descr); 91750dbef1aSdholland /* Use as a default disk if the user has the sets on a local disk */ 91850dbef1aSdholland strlcpy(localfs_dev, disk->dd_name, sizeof localfs_dev); 91950dbef1aSdholland 9204103857bSmartin /* 9214103857bSmartin * Init disk size and geometry 9224103857bSmartin */ 9234103857bSmartin pm->sectorsize = disk->dd_secsize; 9244103857bSmartin pm->dlcyl = disk->dd_cyl; 9254103857bSmartin pm->dlhead = disk->dd_head; 9264103857bSmartin pm->dlsec = disk->dd_sec; 9274103857bSmartin pm->dlsize = disk->dd_totsec; 9284103857bSmartin if (pm->dlsize == 0) 9294103857bSmartin pm->dlsize = disk->dd_cyl * disk->dd_head 9304103857bSmartin * disk->dd_sec; 9314103857bSmartin 9324103857bSmartin pm->parts = partitions_read_disk(pm->diskdev, disk->dd_totsec); 9334103857bSmartin 9344103857bSmartin again: 9354103857bSmartin 9364103857bSmartin #ifdef DEBUG_VERBOSE 9374103857bSmartin if (pm->parts) { 9384103857bSmartin fputs("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", stderr); 9394103857bSmartin dump_parts(pm->parts); 9404103857bSmartin 9414103857bSmartin if (pm->parts->pscheme->secondary_partitions) { 9424103857bSmartin const struct disk_partitions *sparts = 9434103857bSmartin pm->parts->pscheme->secondary_partitions( 94483478358Smartin pm->parts, pm->ptstart, false); 9454103857bSmartin if (sparts != NULL) 9464103857bSmartin dump_parts(sparts); 9474103857bSmartin } 9484103857bSmartin } 9494103857bSmartin #endif 9504103857bSmartin 9514103857bSmartin pm->no_mbr = disk->dd_no_mbr; 9522575b4dcSmartin pm->no_part = disk->dd_no_part; 9532575b4dcSmartin if (!pm->no_part) { 9544b2364d9Smartin pm->sectorsize = disk->dd_secsize; 9554b2364d9Smartin pm->dlcyl = disk->dd_cyl; 9564b2364d9Smartin pm->dlhead = disk->dd_head; 9574b2364d9Smartin pm->dlsec = disk->dd_sec; 9584b2364d9Smartin pm->dlsize = disk->dd_totsec; 9594b2364d9Smartin if (pm->dlsize == 0) 9604103857bSmartin pm->dlsize = disk->dd_cyl * disk->dd_head 9614103857bSmartin * disk->dd_sec; 9624103857bSmartin 9634103857bSmartin if (pm->parts && pm->parts->pscheme->size_limit != 0 9644103857bSmartin && pm->dlsize > pm->parts->pscheme->size_limit 9654103857bSmartin && ! partman_go) { 9664103857bSmartin 9674103857bSmartin char size[5], limit[5]; 9684103857bSmartin 9694103857bSmartin humanize_number(size, sizeof(size), 9704103857bSmartin (uint64_t)pm->dlsize * 512U, 9714103857bSmartin "", HN_AUTOSCALE, HN_B | HN_NOSPACE 9724103857bSmartin | HN_DECIMAL); 9734103857bSmartin 9744103857bSmartin humanize_number(limit, sizeof(limit), 9754103857bSmartin (uint64_t)pm->parts->pscheme->size_limit 9764103857bSmartin * 512U, 9774103857bSmartin "", HN_AUTOSCALE, HN_B | HN_NOSPACE 9784103857bSmartin | HN_DECIMAL); 9794103857bSmartin 9804b2364d9Smartin if (logfp) 9814103857bSmartin fprintf(logfp, 9824103857bSmartin "disk %s: is too big (%" PRIu64 9834103857bSmartin " blocks, %s), will be truncated\n", 9844103857bSmartin pm->diskdev, pm->dlsize, 9854103857bSmartin size); 9864103857bSmartin 9874103857bSmartin msg_display_subst(MSG_toobigdisklabel, 5, 9884103857bSmartin pm->diskdev, 9894103857bSmartin msg_string(pm->parts->pscheme->name), 9904103857bSmartin msg_string(pm->parts->pscheme->short_name), 9914103857bSmartin size, limit); 9924103857bSmartin 9934103857bSmartin int sel = -1; 9944103857bSmartin const char *err = NULL; 9954103857bSmartin process_menu(MENU_convertscheme, &sel); 9964103857bSmartin if (sel == 1) { 9974103857bSmartin if (!delete_scheme(pm)) { 99850dbef1aSdholland return -1; 99950dbef1aSdholland } 10004103857bSmartin goto again; 10014103857bSmartin } else if (sel == 2) { 10024103857bSmartin if (!convert_scheme(pm, 10034103857bSmartin partman_go < 0, &err)) { 10044103857bSmartin if (err != NULL) 10054103857bSmartin err_msg_win(err); 10064103857bSmartin return -1; 10074103857bSmartin } 10084103857bSmartin goto again; 10094103857bSmartin } else if (sel == 3) { 10104103857bSmartin return -1; 10114103857bSmartin } 10124103857bSmartin pm->dlsize = pm->parts->pscheme->size_limit; 10134103857bSmartin } 10142575b4dcSmartin } else { 10152575b4dcSmartin pm->sectorsize = 0; 10162575b4dcSmartin pm->dlcyl = 0; 10172575b4dcSmartin pm->dlhead = 0; 10182575b4dcSmartin pm->dlsec = 0; 10192575b4dcSmartin pm->dlsize = 0; 10202575b4dcSmartin pm->no_mbr = 1; 10212575b4dcSmartin } 10224b2364d9Smartin pm->dlcylsize = pm->dlhead * pm->dlsec; 102350dbef1aSdholland 10244b2364d9Smartin if (partman_go) { 10254b2364d9Smartin pm_getrefdev(pm_new); 10264b2364d9Smartin if (SLIST_EMPTY(&pm_head) || pm_last == NULL) 10274b2364d9Smartin SLIST_INSERT_HEAD(&pm_head, pm_new, l); 10284b2364d9Smartin else 10294b2364d9Smartin SLIST_INSERT_AFTER(pm_last, pm_new, l); 10304103857bSmartin pm_new = malloc(sizeof (struct pm_devs)); 10314b2364d9Smartin memset(pm_new, 0, sizeof *pm_new); 10324b2364d9Smartin } else 10334103857bSmartin /* We are not in partman and do not want to process 10344103857bSmartin * all devices, exit */ 10354b2364d9Smartin break; 10364b2364d9Smartin } 103750dbef1aSdholland 10382575b4dcSmartin return numdisks-skipped; 103950dbef1aSdholland } 104050dbef1aSdholland 104150dbef1aSdholland static int 10424103857bSmartin sort_part_usage_by_mount(const void *a, const void *b) 104350dbef1aSdholland { 10444103857bSmartin const struct part_usage_info *pa = a, *pb = b; 10454103857bSmartin 10464103857bSmartin /* sort all real partitions by mount point */ 10474103857bSmartin if ((pa->instflags & PUIINST_MOUNT) && 10484103857bSmartin (pb->instflags & PUIINST_MOUNT)) 10494103857bSmartin return strcmp(pa->mount, pb->mount); 10504103857bSmartin 10514103857bSmartin /* real partitions go first */ 10524103857bSmartin if (pa->instflags & PUIINST_MOUNT) 10534103857bSmartin return -1; 10544103857bSmartin if (pb->instflags & PUIINST_MOUNT) 10554103857bSmartin return 1; 10564103857bSmartin 10574103857bSmartin /* arbitrary order for all other partitions */ 10584103857bSmartin if (pa->type == PT_swap) 10594103857bSmartin return -1; 10604103857bSmartin if (pb->type == PT_swap) 10614103857bSmartin return 1; 10624103857bSmartin if (pa->type < pb->type) 10634103857bSmartin return -1; 10644103857bSmartin if (pa->type > pb->type) 10654103857bSmartin return 1; 10664103857bSmartin if (pa->cur_part_id < pb->cur_part_id) 10674103857bSmartin return -1; 10684103857bSmartin if (pa->cur_part_id > pb->cur_part_id) 10694103857bSmartin return 1; 10704103857bSmartin return (uintptr_t)a < (uintptr_t)b ? -1 : 1; 107150dbef1aSdholland } 107250dbef1aSdholland 107350dbef1aSdholland int 10744103857bSmartin make_filesystems(struct install_partition_desc *install) 107550dbef1aSdholland { 10764103857bSmartin int error = 0, partno = -1; 10774103857bSmartin char *newfs = NULL, devdev[PATH_MAX], rdev[PATH_MAX]; 10784103857bSmartin size_t i; 10794103857bSmartin struct part_usage_info *ptn; 10804103857bSmartin struct disk_partitions *parts; 10814103857bSmartin const char *mnt_opts = NULL, *fsname = NULL; 108250dbef1aSdholland 1083b1fa9754Smartin if (pm->cur_system) 1084b1fa9754Smartin return 1; 1085b1fa9754Smartin 10862575b4dcSmartin if (pm->no_part) { 10872575b4dcSmartin /* check if this target device already has a ffs */ 10884103857bSmartin snprintf(rdev, sizeof rdev, _PATH_DEV "/r%s", pm->diskdev); 10894103857bSmartin error = fsck_preen(rdev, "ffs", true); 10902575b4dcSmartin if (error) { 10912575b4dcSmartin if (!ask_noyes(MSG_No_filesystem_newfs)) 10922575b4dcSmartin return EINVAL; 10932575b4dcSmartin error = run_program(RUN_DISPLAY | RUN_PROGRESS, 10944103857bSmartin "/sbin/newfs -V2 -O2 %s", rdev); 10952575b4dcSmartin } 10962575b4dcSmartin 10974f30cbf3Smartin md_pre_mount(install, 0); 10982575b4dcSmartin 10992575b4dcSmartin make_target_dir("/"); 11004103857bSmartin 11014103857bSmartin snprintf(devdev, sizeof devdev, _PATH_DEV "%s", pm->diskdev); 11022575b4dcSmartin error = target_mount_do("-o async", devdev, "/"); 11032575b4dcSmartin if (error) { 11044103857bSmartin msg_display_subst(MSG_mountfail, 2, devdev, "/"); 11054103857bSmartin hit_enter_to_continue(NULL, NULL); 11062575b4dcSmartin } 11072575b4dcSmartin 11084103857bSmartin return error; 11094103857bSmartin } 111050dbef1aSdholland 111150dbef1aSdholland /* Making new file systems and mounting them */ 111250dbef1aSdholland 111350dbef1aSdholland /* sort to ensure /usr/local is mounted after /usr (etc) */ 11144103857bSmartin qsort(install->infos, install->num, sizeof(*install->infos), 11154103857bSmartin sort_part_usage_by_mount); 111650dbef1aSdholland 11174103857bSmartin for (i = 0; i < install->num; i++) { 111850dbef1aSdholland /* 111987c16c7aSmartin * Newfs all file systems mareked as needing this. 112087c16c7aSmartin * Mount the ones that have a mountpoint in the target. 112150dbef1aSdholland */ 11224103857bSmartin ptn = &install->infos[i]; 11234103857bSmartin parts = ptn->parts; 11240dfd6624Smartin newfs = NULL; 11250dfd6624Smartin fsname = NULL; 112650dbef1aSdholland 1127a8e7688bSmartin if (ptn->size == 0 || parts == NULL|| ptn->type == PT_swap) 112850dbef1aSdholland continue; 112950dbef1aSdholland 11304103857bSmartin if (parts->pscheme->get_part_device(parts, ptn->cur_part_id, 11314103857bSmartin devdev, sizeof devdev, &partno, parent_device_only, false) 11324103857bSmartin && is_active_rootpart(devdev, partno)) 11334103857bSmartin continue; 11344103857bSmartin 11354103857bSmartin parts->pscheme->get_part_device(parts, ptn->cur_part_id, 11364103857bSmartin devdev, sizeof devdev, &partno, plain_name, true); 11374103857bSmartin 11384103857bSmartin parts->pscheme->get_part_device(parts, ptn->cur_part_id, 11394103857bSmartin rdev, sizeof rdev, &partno, raw_dev_name, true); 11404b2364d9Smartin 11414103857bSmartin switch (ptn->fs_type) { 114250dbef1aSdholland case FS_APPLEUFS: 11434103857bSmartin asprintf(&newfs, "/sbin/newfs"); 11444103857bSmartin mnt_opts = "-tffs -o async"; 11454103857bSmartin fsname = "ffs"; 114650dbef1aSdholland break; 114750dbef1aSdholland case FS_BSDFFS: 114850dbef1aSdholland asprintf(&newfs, 11494103857bSmartin "/sbin/newfs -V2 -O %d", 11504103857bSmartin ptn->fs_version == 2 ? 2 : 1); 11514103857bSmartin if (ptn->mountflags & PUIMNT_LOG) 11524103857bSmartin mnt_opts = "-tffs -o log"; 115350dbef1aSdholland else 11544103857bSmartin mnt_opts = "-tffs -o async"; 11554103857bSmartin fsname = "ffs"; 115650dbef1aSdholland break; 115750dbef1aSdholland case FS_BSDLFS: 11584103857bSmartin asprintf(&newfs, "/sbin/newfs_lfs"); 11594103857bSmartin mnt_opts = "-tlfs"; 11604103857bSmartin fsname = "lfs"; 116150dbef1aSdholland break; 116250dbef1aSdholland case FS_MSDOS: 116350dbef1aSdholland asprintf(&newfs, "/sbin/newfs_msdos"); 11644103857bSmartin mnt_opts = "-tmsdos"; 11654103857bSmartin fsname = "msdos"; 116650dbef1aSdholland break; 116750dbef1aSdholland case FS_SYSVBFS: 116850dbef1aSdholland asprintf(&newfs, "/sbin/newfs_sysvbfs"); 11694103857bSmartin mnt_opts = "-tsysvbfs"; 11704103857bSmartin fsname = "sysvbfs"; 117150dbef1aSdholland break; 11720dfd6624Smartin case FS_V7: 11730dfd6624Smartin asprintf(&newfs, "/sbin/newfs_v7fs"); 11740dfd6624Smartin mnt_opts = "-tv7fs"; 11750dfd6624Smartin fsname = "v7fs"; 11760dfd6624Smartin break; 117750dbef1aSdholland case FS_EX2FS: 117850dbef1aSdholland asprintf(&newfs, "/sbin/newfs_ext2fs"); 11794103857bSmartin mnt_opts = "-text2fs"; 11804103857bSmartin fsname = "ext2fs"; 118150dbef1aSdholland break; 118250dbef1aSdholland } 11834103857bSmartin if ((ptn->instflags & PUIINST_NEWFS) && newfs != NULL) { 11844103857bSmartin if (ptn->fs_type == FS_MSDOS) { 118550dbef1aSdholland /* newfs only if mount fails */ 118650dbef1aSdholland if (run_program(RUN_SILENT | RUN_ERROR_OK, 11874103857bSmartin "mount -rt msdos %s /mnt2", devdev) != 0) 118850dbef1aSdholland error = run_program( 118950dbef1aSdholland RUN_DISPLAY | RUN_PROGRESS, 11904103857bSmartin "%s %s", 11914103857bSmartin newfs, rdev); 119250dbef1aSdholland else { 119350dbef1aSdholland run_program(RUN_SILENT | RUN_ERROR_OK, 119450dbef1aSdholland "umount /mnt2"); 119550dbef1aSdholland error = 0; 119650dbef1aSdholland } 11974103857bSmartin } else { 119850dbef1aSdholland error = run_program(RUN_DISPLAY | RUN_PROGRESS, 11994103857bSmartin "%s %s", newfs, rdev); 12004103857bSmartin } 12010dfd6624Smartin } else if ((ptn->instflags & (PUIINST_MOUNT|PUIINST_BOOT)) 12020dfd6624Smartin && fsname != NULL) { 120350dbef1aSdholland /* We'd better check it isn't dirty */ 12044103857bSmartin error = fsck_preen(devdev, fsname, false); 120550dbef1aSdholland } 120650dbef1aSdholland free(newfs); 12074103857bSmartin if (error != 0) 120850dbef1aSdholland return error; 120950dbef1aSdholland 12104103857bSmartin ptn->instflags &= ~PUIINST_NEWFS; 12114f30cbf3Smartin md_pre_mount(install, i); 121250dbef1aSdholland 12134103857bSmartin if (partman_go == 0 && (ptn->instflags & PUIINST_MOUNT) && 12144103857bSmartin mnt_opts != NULL) { 12154103857bSmartin make_target_dir(ptn->mount); 12164103857bSmartin error = target_mount_do(mnt_opts, devdev, 12174103857bSmartin ptn->mount); 121850dbef1aSdholland if (error) { 12194103857bSmartin msg_display_subst(MSG_mountfail, 2, devdev, 12204103857bSmartin ptn->mount); 12214103857bSmartin hit_enter_to_continue(NULL, NULL); 122250dbef1aSdholland return error; 122350dbef1aSdholland } 122450dbef1aSdholland } 122550dbef1aSdholland } 122650dbef1aSdholland return 0; 122750dbef1aSdholland } 122850dbef1aSdholland 122950dbef1aSdholland int 12304103857bSmartin make_fstab(struct install_partition_desc *install) 123150dbef1aSdholland { 123250dbef1aSdholland FILE *f; 12334103857bSmartin const char *dump_dev = NULL; 12344103857bSmartin const char *dev; 12354103857bSmartin char dev_buf[PATH_MAX], swap_dev[PATH_MAX]; 12364103857bSmartin 1237b1fa9754Smartin if (pm->cur_system) 1238b1fa9754Smartin return 1; 1239b1fa9754Smartin 12404103857bSmartin swap_dev[0] = 0; 124150dbef1aSdholland 124250dbef1aSdholland /* Create the fstab. */ 124350dbef1aSdholland make_target_dir("/etc"); 124450dbef1aSdholland f = target_fopen("/etc/fstab", "w"); 124550dbef1aSdholland scripting_fprintf(NULL, "cat <<EOF >%s/etc/fstab\n", target_prefix()); 124650dbef1aSdholland 12474b2364d9Smartin if (logfp) 12484b2364d9Smartin (void)fprintf(logfp, 12494103857bSmartin "Making %s/etc/fstab (%s).\n", target_prefix(), 12504103857bSmartin pm->diskdev); 12514b2364d9Smartin 125250dbef1aSdholland if (f == NULL) { 125350dbef1aSdholland msg_display(MSG_createfstab); 125450dbef1aSdholland if (logfp) 125550dbef1aSdholland (void)fprintf(logfp, "Failed to make /etc/fstab!\n"); 12564103857bSmartin hit_enter_to_continue(NULL, NULL); 12574b2364d9Smartin #ifndef DEBUG 125850dbef1aSdholland return 1; 125950dbef1aSdholland #else 126050dbef1aSdholland f = stdout; 126150dbef1aSdholland #endif 126250dbef1aSdholland } 126350dbef1aSdholland 1264c52e6b59Smartin scripting_fprintf(f, "# NetBSD /etc/fstab\n# See /usr/share/examples/" 1265c52e6b59Smartin "fstab/ for more examples.\n"); 12662575b4dcSmartin 12672575b4dcSmartin if (pm->no_part) { 12682575b4dcSmartin /* single dk? target */ 12692575b4dcSmartin char buf[200], parent[200], swap[200], *prompt; 12702575b4dcSmartin int res; 12712575b4dcSmartin 12722575b4dcSmartin if (!get_name_and_parent(pm->diskdev, buf, parent)) 12732575b4dcSmartin goto done_with_disks; 1274a7267d53Smartin scripting_fprintf(f, NAME_PREFIX "%s\t/\tffs\trw\t\t1 1\n", 12752575b4dcSmartin buf); 12762575b4dcSmartin if (!find_swap_part_on(parent, swap)) 12772575b4dcSmartin goto done_with_disks; 12784103857bSmartin const char *args[] = { parent, swap }; 12794103857bSmartin prompt = str_arg_subst(msg_string(MSG_Auto_add_swap_part), 12804103857bSmartin __arraycount(args), args); 12812575b4dcSmartin res = ask_yesno(prompt); 12822575b4dcSmartin free(prompt); 12832575b4dcSmartin if (res) 1284a7267d53Smartin scripting_fprintf(f, NAME_PREFIX "%s\tnone" 12852575b4dcSmartin "\tswap\tsw,dp\t\t0 0\n", swap); 12862575b4dcSmartin goto done_with_disks; 12872575b4dcSmartin } 12882575b4dcSmartin 12894103857bSmartin for (size_t i = 0; i < install->num; i++) { 12904103857bSmartin 12914103857bSmartin const struct part_usage_info *ptn = &install->infos[i]; 12924103857bSmartin 12934103857bSmartin if (ptn->type != PT_swap && 12944103857bSmartin (ptn->instflags & PUIINST_MOUNT) == 0) 12954103857bSmartin continue; 12964103857bSmartin 129750dbef1aSdholland const char *s = ""; 12984103857bSmartin const char *mp = ptn->mount; 129950dbef1aSdholland const char *fstype = "ffs"; 130050dbef1aSdholland int fsck_pass = 0, dump_freq = 0; 130150dbef1aSdholland 13024103857bSmartin if (ptn->parts->pscheme->get_part_device(ptn->parts, 13034103857bSmartin ptn->cur_part_id, dev_buf, sizeof dev_buf, NULL, 13044103857bSmartin logical_name, true)) 13054103857bSmartin dev = dev_buf; 13064b2364d9Smartin else 13074103857bSmartin dev = NULL; 13084b2364d9Smartin 130950dbef1aSdholland if (!*mp) { 131050dbef1aSdholland /* 131150dbef1aSdholland * No mount point specified, comment out line and 131250dbef1aSdholland * use /mnt as a placeholder for the mount point. 131350dbef1aSdholland */ 131450dbef1aSdholland s = "# "; 131550dbef1aSdholland mp = "/mnt"; 131650dbef1aSdholland } 131750dbef1aSdholland 13184103857bSmartin switch (ptn->fs_type) { 131950dbef1aSdholland case FS_UNUSED: 132050dbef1aSdholland continue; 132150dbef1aSdholland case FS_BSDLFS: 132250dbef1aSdholland /* If there is no LFS, just comment it out. */ 132350dbef1aSdholland if (!check_lfs_progs()) 132450dbef1aSdholland s = "# "; 132550dbef1aSdholland fstype = "lfs"; 132650dbef1aSdholland /* FALLTHROUGH */ 132750dbef1aSdholland case FS_BSDFFS: 132850dbef1aSdholland fsck_pass = (strcmp(mp, "/") == 0) ? 1 : 2; 132950dbef1aSdholland dump_freq = 1; 133050dbef1aSdholland break; 133150dbef1aSdholland case FS_MSDOS: 133250dbef1aSdholland fstype = "msdos"; 133350dbef1aSdholland break; 133450dbef1aSdholland case FS_SWAP: 13354103857bSmartin if (swap_dev[0] == 0) { 13364103857bSmartin strncpy(swap_dev, dev, sizeof swap_dev); 133750dbef1aSdholland dump_dev = ",dp"; 133850dbef1aSdholland } else { 133950dbef1aSdholland dump_dev = ""; 134050dbef1aSdholland } 13414103857bSmartin scripting_fprintf(f, "%s\t\tnone\tswap\tsw%s\t\t 0 0\n", 13424b2364d9Smartin dev, dump_dev); 134350dbef1aSdholland continue; 134450dbef1aSdholland case FS_SYSVBFS: 134550dbef1aSdholland fstype = "sysvbfs"; 134650dbef1aSdholland make_target_dir("/stand"); 134750dbef1aSdholland break; 134850dbef1aSdholland default: 134950dbef1aSdholland fstype = "???"; 135050dbef1aSdholland s = "# "; 135150dbef1aSdholland break; 135250dbef1aSdholland } 135350dbef1aSdholland /* The code that remounts root rw doesn't check the partition */ 13544103857bSmartin if (strcmp(mp, "/") == 0 && 13554103857bSmartin (ptn->instflags & PUIINST_MOUNT) == 0) 135650dbef1aSdholland s = "# "; 135750dbef1aSdholland 135850dbef1aSdholland scripting_fprintf(f, 13594103857bSmartin "%s%s\t\t%s\t%s\trw%s%s%s%s%s%s%s%s\t\t %d %d\n", 13604b2364d9Smartin s, dev, mp, fstype, 13614103857bSmartin ptn->mountflags & PUIMNT_LOG ? ",log" : "", 1362b8a71b59Smartin ptn->mountflags & PUIMNT_NOAUTO ? ",noauto" : "", 13634103857bSmartin ptn->mountflags & PUIMNT_ASYNC ? ",async" : "", 13644103857bSmartin ptn->mountflags & PUIMNT_NOATIME ? ",noatime" : "", 13654103857bSmartin ptn->mountflags & PUIMNT_NODEV ? ",nodev" : "", 13664103857bSmartin ptn->mountflags & PUIMNT_NODEVMTIME ? ",nodevmtime" : "", 13674103857bSmartin ptn->mountflags & PUIMNT_NOEXEC ? ",noexec" : "", 13684103857bSmartin ptn->mountflags & PUIMNT_NOSUID ? ",nosuid" : "", 136950dbef1aSdholland dump_freq, fsck_pass); 137050dbef1aSdholland } 13714103857bSmartin 13722575b4dcSmartin done_with_disks: 13734103857bSmartin if (tmp_ramdisk_size > 0) { 137450dbef1aSdholland #ifdef HAVE_TMPFS 137550dbef1aSdholland scripting_fprintf(f, "tmpfs\t\t/tmp\ttmpfs\trw,-m=1777,-s=%" 13764103857bSmartin PRIu64 "\n", 137750dbef1aSdholland tmp_ramdisk_size * 512); 137850dbef1aSdholland #else 13794103857bSmartin if (swap_dev[0] != 0) 13804103857bSmartin scripting_fprintf(f, "%s\t\t/tmp\tmfs\trw,-s=%" 13814103857bSmartin PRIu64 "\n", swap_dev, tmp_ramdisk_size); 138250dbef1aSdholland else 138350dbef1aSdholland scripting_fprintf(f, "swap\t\t/tmp\tmfs\trw,-s=%" 13844103857bSmartin PRIu64 "\n", tmp_ramdisk_size); 138550dbef1aSdholland #endif 138650dbef1aSdholland } 138750dbef1aSdholland 13883b44a3d7Smartin if (cdrom_dev[0] == 0) 13893b44a3d7Smartin get_default_cdrom(cdrom_dev, sizeof(cdrom_dev)); 13903b44a3d7Smartin 139150dbef1aSdholland /* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */ 139250dbef1aSdholland scripting_fprintf(f, "kernfs\t\t/kern\tkernfs\trw\n"); 139350dbef1aSdholland scripting_fprintf(f, "ptyfs\t\t/dev/pts\tptyfs\trw\n"); 139450dbef1aSdholland scripting_fprintf(f, "procfs\t\t/proc\tprocfs\trw\n"); 139550dbef1aSdholland scripting_fprintf(f, "/dev/%s\t\t/cdrom\tcd9660\tro,noauto\n", 13963b44a3d7Smartin cdrom_dev); 139750dbef1aSdholland scripting_fprintf(f, "%stmpfs\t\t/var/shm\ttmpfs\trw,-m1777,-sram%%25\n", 139850dbef1aSdholland tmpfs_on_var_shm() ? "" : "#"); 139950dbef1aSdholland make_target_dir("/kern"); 140050dbef1aSdholland make_target_dir("/proc"); 140150dbef1aSdholland make_target_dir("/dev/pts"); 140250dbef1aSdholland make_target_dir("/cdrom"); 140350dbef1aSdholland make_target_dir("/var/shm"); 140450dbef1aSdholland 140550dbef1aSdholland scripting_fprintf(NULL, "EOF\n"); 140650dbef1aSdholland 140750dbef1aSdholland fclose(f); 140850dbef1aSdholland fflush(NULL); 140950dbef1aSdholland return 0; 141050dbef1aSdholland } 141150dbef1aSdholland 1412a7267d53Smartin static bool 1413a7267d53Smartin find_part_by_name(const char *name, struct disk_partitions **parts, 1414a7267d53Smartin part_id *pno) 141550dbef1aSdholland { 1416a7267d53Smartin struct pm_devs *i; 1417a7267d53Smartin struct disk_partitions *ps; 1418a7267d53Smartin part_id id; 1419a7267d53Smartin struct disk_desc disks[MAX_DISKS]; 1420a7267d53Smartin int n, cnt; 142150dbef1aSdholland 1422a7267d53Smartin if (SLIST_EMPTY(&pm_head)) { 1423a7267d53Smartin /* 1424a7267d53Smartin * List has not been filled, only "pm" is valid - check 1425a7267d53Smartin * that first. 1426a7267d53Smartin */ 1427a7267d53Smartin if (pm->parts->pscheme->find_by_name != NULL) { 1428a7267d53Smartin id = pm->parts->pscheme->find_by_name(pm->parts, name); 1429a7267d53Smartin if (id != NO_PART) { 1430a7267d53Smartin *pno = id; 1431a7267d53Smartin *parts = pm->parts; 1432a7267d53Smartin return true; 1433a7267d53Smartin } 1434a7267d53Smartin } 1435a7267d53Smartin /* 1436a7267d53Smartin * Not that easy - check all other disks 1437a7267d53Smartin */ 1438a7267d53Smartin cnt = get_disks(disks, false); 1439a7267d53Smartin for (n = 0; n < cnt; n++) { 1440a7267d53Smartin if (strcmp(disks[n].dd_name, pm->diskdev) == 0) 1441a7267d53Smartin continue; 1442a7267d53Smartin ps = partitions_read_disk(disks[n].dd_name, 1443a7267d53Smartin disks[n].dd_totsec); 1444a7267d53Smartin if (ps == NULL) 1445a7267d53Smartin continue; 1446a7267d53Smartin if (ps->pscheme->find_by_name == NULL) 1447a7267d53Smartin continue; 1448a7267d53Smartin id = ps->pscheme->find_by_name(ps, name); 1449a7267d53Smartin if (id != NO_PART) { 1450a7267d53Smartin *pno = id; 1451a7267d53Smartin *parts = ps; 1452a7267d53Smartin return true; /* XXX this leaks memory */ 1453a7267d53Smartin } 1454a7267d53Smartin ps->pscheme->free(ps); 1455a7267d53Smartin } 14566de47033Smartin } else { 1457a7267d53Smartin SLIST_FOREACH(i, &pm_head, l) { 1458a7267d53Smartin if (i->parts == NULL) 1459a7267d53Smartin continue; 1460a7267d53Smartin if (i->parts->pscheme->find_by_name == NULL) 1461a7267d53Smartin continue; 1462a7267d53Smartin id = i->parts->pscheme->find_by_name(i->parts, name); 1463a7267d53Smartin if (id == NO_PART) 1464a7267d53Smartin continue; 1465a7267d53Smartin *pno = id; 1466a7267d53Smartin *parts = i->parts; 1467a7267d53Smartin return true; 1468a7267d53Smartin } 14696de47033Smartin } 14706de47033Smartin 1471a7267d53Smartin *pno = NO_PART; 1472a7267d53Smartin *parts = NULL; 1473a7267d53Smartin return false; 1474a7267d53Smartin } 1475a7267d53Smartin 1476a7267d53Smartin static int 1477a7267d53Smartin /*ARGSUSED*/ 1478a7267d53Smartin process_found_fs(struct data *list, size_t num, const struct lookfor *item, 1479a7267d53Smartin bool with_fsck) 1480a7267d53Smartin { 1481a7267d53Smartin int error; 1482a7267d53Smartin char rdev[PATH_MAX], dev[PATH_MAX], 1483a7267d53Smartin options[STRSIZE], tmp[STRSIZE], *op, *last; 1484a7267d53Smartin const char *fsname = (const char*)item->var; 1485a7267d53Smartin part_id pno; 1486a7267d53Smartin struct disk_partitions *parts; 1487*d7f55badSmartin size_t len; 1488*d7f55badSmartin bool first, is_root; 1489a7267d53Smartin 1490a7267d53Smartin if (num < 2 || strstr(list[2].u.s_val, "noauto") != NULL) 1491a7267d53Smartin return 0; 1492a7267d53Smartin 1493*d7f55badSmartin is_root = strcmp(list[1].u.s_val, "/") == 0; 1494*d7f55badSmartin if (is_root && target_mounted()) 1495a7267d53Smartin return 0; 1496a7267d53Smartin 1497a7267d53Smartin if (strcmp(item->head, name_prefix) == 0) { 1498a7267d53Smartin /* this fstab entry uses NAME= syntax */ 1499a7267d53Smartin if (!find_part_by_name(list[0].u.s_val, 1500a7267d53Smartin &parts, &pno) || parts == NULL || pno == NO_PART) 1501a7267d53Smartin return 0; 1502a7267d53Smartin parts->pscheme->get_part_device(parts, pno, 1503a7267d53Smartin dev, sizeof(dev), NULL, plain_name, true); 1504a7267d53Smartin parts->pscheme->get_part_device(parts, pno, 1505a7267d53Smartin rdev, sizeof(rdev), NULL, raw_dev_name, true); 1506a7267d53Smartin } else { 1507*d7f55badSmartin /* this fstab entry uses the plain device name */ 1508*d7f55badSmartin if (is_root) { 1509*d7f55badSmartin /* 1510*d7f55badSmartin * PR 54480: we can not use the current device name 1511*d7f55badSmartin * as it might be different from the real environment. 1512*d7f55badSmartin * This is an abuse of the functionality, but it used 1513*d7f55badSmartin * to work before (and still does work if only a single 1514*d7f55badSmartin * target disk is involved). 1515*d7f55badSmartin * Use the device name from the current "pm" instead. 1516*d7f55badSmartin */ 1517*d7f55badSmartin strcpy(rdev, "/dev/r"); 1518*d7f55badSmartin strlcat(rdev, pm->diskdev, sizeof(rdev)); 1519*d7f55badSmartin strcpy(dev, "/dev/"); 1520*d7f55badSmartin strlcat(dev, pm->diskdev, sizeof(dev)); 1521*d7f55badSmartin /* copy over the partition letter, if any */ 1522*d7f55badSmartin len = strlen(list[0].u.s_val); 1523*d7f55badSmartin if (list[0].u.s_val[len-1] >= 'a' && 1524*d7f55badSmartin list[0].u.s_val[len-1] <= 1525*d7f55badSmartin ('a' + getmaxpartitions())) { 1526*d7f55badSmartin strlcat(rdev, &list[0].u.s_val[len-1], 1527*d7f55badSmartin sizeof(rdev)); 1528*d7f55badSmartin strlcat(dev, &list[0].u.s_val[len-1], 1529*d7f55badSmartin sizeof(dev)); 1530*d7f55badSmartin } 1531*d7f55badSmartin } else { 1532a7267d53Smartin strcpy(rdev, "/dev/r"); 1533a7267d53Smartin strlcat(rdev, list[0].u.s_val, sizeof(rdev)); 1534a7267d53Smartin strcpy(dev, "/dev/"); 1535a7267d53Smartin strlcat(dev, list[0].u.s_val, sizeof(dev)); 1536a7267d53Smartin } 1537*d7f55badSmartin } 1538a7267d53Smartin 1539a7267d53Smartin if (with_fsck) { 1540a7267d53Smartin /* need the raw device for fsck_preen */ 1541a7267d53Smartin error = fsck_preen(rdev, fsname, false); 154250dbef1aSdholland if (error != 0) 154350dbef1aSdholland return error; 1544a7267d53Smartin } 154550dbef1aSdholland 1546a7267d53Smartin /* add mount option for fs type */ 1547a7267d53Smartin strcpy(options, "-t "); 1548a7267d53Smartin strlcat(options, fsname, sizeof(options)); 1549a7267d53Smartin 1550a7267d53Smartin /* extract mount options from fstab */ 1551a7267d53Smartin strlcpy(tmp, list[2].u.s_val, sizeof(tmp)); 1552a7267d53Smartin for (first = true, op = strtok_r(tmp, ",", &last); op != NULL; 1553a7267d53Smartin op = strtok_r(NULL, ",", &last)) { 1554a7267d53Smartin if (strcmp(op, FSTAB_RW) == 0 || 1555a7267d53Smartin strcmp(op, FSTAB_RQ) == 0 || 1556a7267d53Smartin strcmp(op, FSTAB_RO) == 0 || 1557a7267d53Smartin strcmp(op, FSTAB_SW) == 0 || 1558a7267d53Smartin strcmp(op, FSTAB_DP) == 0 || 1559a7267d53Smartin strcmp(op, FSTAB_XX) == 0) 1560a7267d53Smartin continue; 1561a7267d53Smartin if (first) { 1562a7267d53Smartin first = false; 1563a7267d53Smartin strlcat(options, " -o ", sizeof(options)); 1564a7267d53Smartin } else { 1565a7267d53Smartin strlcat(options, ",", sizeof(options)); 1566a7267d53Smartin } 1567a7267d53Smartin strlcat(options, op, sizeof(options)); 1568a7267d53Smartin } 1569a7267d53Smartin 1570a7267d53Smartin error = target_mount(options, dev, list[1].u.s_val); 157150dbef1aSdholland if (error != 0) { 157224ecf24eSchristos msg_fmt_display(MSG_mount_failed, "%s", list[0].u.s_val); 1573e21052b4Smartin if (!ask_noyes(NULL)) 157450dbef1aSdholland return error; 157550dbef1aSdholland } 157650dbef1aSdholland return 0; 157750dbef1aSdholland } 157850dbef1aSdholland 157950dbef1aSdholland static int 158050dbef1aSdholland /*ARGSUSED*/ 1581a7267d53Smartin found_fs(struct data *list, size_t num, const struct lookfor *item) 158250dbef1aSdholland { 1583a7267d53Smartin return process_found_fs(list, num, item, true); 158450dbef1aSdholland } 1585a7267d53Smartin 1586a7267d53Smartin static int 1587a7267d53Smartin /*ARGSUSED*/ 1588a7267d53Smartin found_fs_nocheck(struct data *list, size_t num, const struct lookfor *item) 1589a7267d53Smartin { 1590a7267d53Smartin return process_found_fs(list, num, item, false); 1591a7267d53Smartin } 159250dbef1aSdholland 159350dbef1aSdholland /* 159450dbef1aSdholland * Do an fsck. On failure, inform the user by showing a warning 159550dbef1aSdholland * message and doing menu_ok() before proceeding. 15964103857bSmartin * The device passed should be the full qualified path to raw disk 15974103857bSmartin * (e.g. /dev/rwd0a). 159850dbef1aSdholland * Returns 0 on success, or nonzero return code from fsck() on failure. 159950dbef1aSdholland */ 160050dbef1aSdholland static int 16014103857bSmartin fsck_preen(const char *disk, const char *fsname, bool silent) 160250dbef1aSdholland { 16034103857bSmartin char *prog, err[12]; 160450dbef1aSdholland int error; 160550dbef1aSdholland 160650dbef1aSdholland if (fsname == NULL) 160750dbef1aSdholland return 0; 160850dbef1aSdholland /* first, check if fsck program exists, if not, assume ok */ 160950dbef1aSdholland asprintf(&prog, "/sbin/fsck_%s", fsname); 161050dbef1aSdholland if (prog == NULL) 161150dbef1aSdholland return 0; 16124d3ac9f2Smartin if (access(prog, X_OK) != 0) { 16134d3ac9f2Smartin free(prog); 161450dbef1aSdholland return 0; 16154d3ac9f2Smartin } 161650dbef1aSdholland if (!strcmp(fsname,"ffs")) 16174103857bSmartin fixsb(prog, disk); 16184103857bSmartin error = run_program(silent? RUN_SILENT|RUN_ERROR_OK : 0, "%s -p -q %s", prog, disk); 161950dbef1aSdholland free(prog); 16202575b4dcSmartin if (error != 0 && !silent) { 16214103857bSmartin sprintf(err, "%d", error); 16224103857bSmartin msg_display_subst(msg_string(MSG_badfs), 3, 16234103857bSmartin disk, fsname, err); 1624e21052b4Smartin if (ask_noyes(NULL)) 162550dbef1aSdholland error = 0; 162650dbef1aSdholland /* XXX at this point maybe we should run a full fsck? */ 162750dbef1aSdholland } 162850dbef1aSdholland return error; 162950dbef1aSdholland } 163050dbef1aSdholland 163150dbef1aSdholland /* This performs the same function as the etc/rc.d/fixsb script 163250dbef1aSdholland * which attempts to correct problems with ffs1 filesystems 163350dbef1aSdholland * which may have been introduced by booting a netbsd-current kernel 163450dbef1aSdholland * from between April of 2003 and January 2004. For more information 163550dbef1aSdholland * This script was developed as a response to NetBSD pr install/25138 163650dbef1aSdholland * Additional prs regarding the original issue include: 163750dbef1aSdholland * bin/17910 kern/21283 kern/21404 port-macppc/23925 port-macppc/23926 163850dbef1aSdholland */ 163950dbef1aSdholland static void 16404103857bSmartin fixsb(const char *prog, const char *disk) 164150dbef1aSdholland { 164250dbef1aSdholland int fd; 164350dbef1aSdholland int rval; 164450dbef1aSdholland union { 164550dbef1aSdholland struct fs fs; 164650dbef1aSdholland char buf[SBLOCKSIZE]; 164750dbef1aSdholland } sblk; 164850dbef1aSdholland struct fs *fs = &sblk.fs; 164950dbef1aSdholland 16504103857bSmartin fd = open(disk, O_RDONLY); 165150dbef1aSdholland if (fd == -1) 165250dbef1aSdholland return; 165350dbef1aSdholland 165450dbef1aSdholland /* Read ffsv1 main superblock */ 165550dbef1aSdholland rval = pread(fd, sblk.buf, sizeof sblk.buf, SBLOCK_UFS1); 165650dbef1aSdholland close(fd); 165750dbef1aSdholland if (rval != sizeof sblk.buf) 165850dbef1aSdholland return; 165950dbef1aSdholland 166050dbef1aSdholland if (fs->fs_magic != FS_UFS1_MAGIC && 166150dbef1aSdholland fs->fs_magic != FS_UFS1_MAGIC_SWAPPED) 166250dbef1aSdholland /* Not FFSv1 */ 166350dbef1aSdholland return; 166450dbef1aSdholland if (fs->fs_old_flags & FS_FLAGS_UPDATED) 166550dbef1aSdholland /* properly updated fslevel 4 */ 166650dbef1aSdholland return; 166750dbef1aSdholland if (fs->fs_bsize != fs->fs_maxbsize) 166850dbef1aSdholland /* not messed up */ 166950dbef1aSdholland return; 167050dbef1aSdholland 167150dbef1aSdholland /* 167250dbef1aSdholland * OK we have a munged fs, first 'upgrade' to fslevel 4, 167350dbef1aSdholland * We specify -b16 in order to stop fsck bleating that the 167450dbef1aSdholland * sb doesn't match the first alternate. 167550dbef1aSdholland */ 167650dbef1aSdholland run_program(RUN_DISPLAY | RUN_PROGRESS, 16774103857bSmartin "%s -p -b 16 -c 4 %s", prog, disk); 167850dbef1aSdholland /* Then downgrade to fslevel 3 */ 167950dbef1aSdholland run_program(RUN_DISPLAY | RUN_PROGRESS, 16804103857bSmartin "%s -p -c 3 %s", prog, disk); 168150dbef1aSdholland } 168250dbef1aSdholland 168350dbef1aSdholland /* 168450dbef1aSdholland * fsck and mount the root partition. 16854103857bSmartin * devdev is the fully qualified block device name. 168650dbef1aSdholland */ 168750dbef1aSdholland static int 1688a7267d53Smartin mount_root(const char *devdev, bool first, bool writeable, 1689a7267d53Smartin struct install_partition_desc *install) 169050dbef1aSdholland { 169150dbef1aSdholland int error; 169250dbef1aSdholland 16934103857bSmartin error = fsck_preen(devdev, "ffs", false); 169450dbef1aSdholland if (error != 0) 169550dbef1aSdholland return error; 169650dbef1aSdholland 1697a7267d53Smartin if (first) 16984f30cbf3Smartin md_pre_mount(install, 0); 169950dbef1aSdholland 17004103857bSmartin /* Mount devdev on target's "". 170150dbef1aSdholland * If we pass "" as mount-on, Prefixing will DTRT. 170250dbef1aSdholland * for now, use no options. 170350dbef1aSdholland * XXX consider -o remount in case target root is 170450dbef1aSdholland * current root, still readonly from single-user? 170550dbef1aSdholland */ 1706a7267d53Smartin return target_mount(writeable? "" : "-r", devdev, ""); 170750dbef1aSdholland } 170850dbef1aSdholland 170950dbef1aSdholland /* Get information on the file systems mounted from the root filesystem. 171050dbef1aSdholland * Offer to convert them into 4.4BSD inodes if they are not 4.4BSD 171150dbef1aSdholland * inodes. Fsck them. Mount them. 171250dbef1aSdholland */ 171350dbef1aSdholland 171450dbef1aSdholland int 17154103857bSmartin mount_disks(struct install_partition_desc *install) 171650dbef1aSdholland { 171750dbef1aSdholland char *fstab; 171850dbef1aSdholland int fstabsize; 171950dbef1aSdholland int error; 17204103857bSmartin char devdev[PATH_MAX]; 1721a7267d53Smartin size_t i, num_fs_types, num_entries; 1722a7267d53Smartin struct lookfor *fstabbuf, *l; 172350dbef1aSdholland 1724b1fa9754Smartin if (install->cur_system) 1725b1fa9754Smartin return 0; 1726b1fa9754Smartin 1727a7267d53Smartin /* 1728a7267d53Smartin * Check what file system tools are available and create parsers 1729a7267d53Smartin * for the corresponding fstab(5) entries - all others will be 1730a7267d53Smartin * ignored. 1731a7267d53Smartin */ 1732a7267d53Smartin num_fs_types = 1; /* ffs is implicit */ 1733a7267d53Smartin for (i = 0; i < __arraycount(extern_fs_with_chk); i++) { 1734a7267d53Smartin sprintf(devdev, "/sbin/newfs_%s", extern_fs_with_chk[i]); 1735a7267d53Smartin if (file_exists_p(devdev)) 1736a7267d53Smartin num_fs_types++; 1737a7267d53Smartin } 1738a7267d53Smartin for (i = 0; i < __arraycount(extern_fs_newfs_only); i++) { 1739a7267d53Smartin sprintf(devdev, "/sbin/newfs_%s", extern_fs_newfs_only[i]); 1740a7267d53Smartin if (file_exists_p(devdev)) 1741a7267d53Smartin num_fs_types++; 1742a7267d53Smartin } 1743a7267d53Smartin num_entries = 2 * num_fs_types + 1; /* +1 for "ufs" special case */ 1744a7267d53Smartin fstabbuf = calloc(num_entries, sizeof(*fstabbuf)); 1745a7267d53Smartin if (fstabbuf == NULL) 1746a7267d53Smartin return -1; 1747a7267d53Smartin l = fstabbuf; 1748a7267d53Smartin l->head = "/dev/"; 1749a7267d53Smartin l->fmt = strdup("/dev/%s %s ffs %s"); 1750a7267d53Smartin l->todo = "c"; 1751a7267d53Smartin l->var = __UNCONST("ffs"); 1752a7267d53Smartin l->func = found_fs; 1753a7267d53Smartin l++; 1754a7267d53Smartin l->head = "/dev/"; 1755a7267d53Smartin l->fmt = strdup("/dev/%s %s ufs %s"); 1756a7267d53Smartin l->todo = "c"; 1757a7267d53Smartin l->var = __UNCONST("ffs"); 1758a7267d53Smartin l->func = found_fs; 1759a7267d53Smartin l++; 1760a7267d53Smartin l->head = NAME_PREFIX; 1761a7267d53Smartin l->fmt = strdup(NAME_PREFIX "%s %s ffs %s"); 1762a7267d53Smartin l->todo = "c"; 1763a7267d53Smartin l->var = __UNCONST("ffs"); 1764a7267d53Smartin l->func = found_fs; 1765a7267d53Smartin l++; 1766a7267d53Smartin for (i = 0; i < __arraycount(extern_fs_with_chk); i++) { 1767a7267d53Smartin sprintf(devdev, "/sbin/newfs_%s", extern_fs_with_chk[i]); 1768a7267d53Smartin if (!file_exists_p(devdev)) 1769a7267d53Smartin continue; 1770a7267d53Smartin sprintf(devdev, "/dev/%%s %%s %s %%s", extern_fs_with_chk[i]); 1771a7267d53Smartin l->head = "/dev/"; 1772a7267d53Smartin l->fmt = strdup(devdev); 1773a7267d53Smartin l->todo = "c"; 1774a7267d53Smartin l->var = __UNCONST(extern_fs_with_chk[i]); 1775a7267d53Smartin l->func = found_fs; 1776a7267d53Smartin l++; 1777a7267d53Smartin sprintf(devdev, NAME_PREFIX "%%s %%s %s %%s", 1778a7267d53Smartin extern_fs_with_chk[i]); 1779a7267d53Smartin l->head = NAME_PREFIX; 1780a7267d53Smartin l->fmt = strdup(devdev); 1781a7267d53Smartin l->todo = "c"; 1782a7267d53Smartin l->var = __UNCONST(extern_fs_with_chk[i]); 1783a7267d53Smartin l->func = found_fs; 1784a7267d53Smartin l++; 1785a7267d53Smartin } 1786a7267d53Smartin for (i = 0; i < __arraycount(extern_fs_newfs_only); i++) { 1787a7267d53Smartin sprintf(devdev, "/sbin/newfs_%s", extern_fs_newfs_only[i]); 1788a7267d53Smartin if (!file_exists_p(devdev)) 1789a7267d53Smartin continue; 1790a7267d53Smartin sprintf(devdev, "/dev/%%s %%s %s %%s", extern_fs_newfs_only[i]); 1791a7267d53Smartin l->head = "/dev/"; 1792a7267d53Smartin l->fmt = strdup(devdev); 1793a7267d53Smartin l->todo = "c"; 1794a7267d53Smartin l->var = __UNCONST(extern_fs_newfs_only[i]); 1795a7267d53Smartin l->func = found_fs_nocheck; 1796a7267d53Smartin l++; 1797a7267d53Smartin sprintf(devdev, NAME_PREFIX "%%s %%s %s %%s", 1798a7267d53Smartin extern_fs_newfs_only[i]); 1799a7267d53Smartin l->head = NAME_PREFIX; 1800a7267d53Smartin l->fmt = strdup(devdev); 1801a7267d53Smartin l->todo = "c"; 1802a7267d53Smartin l->var = __UNCONST(extern_fs_newfs_only[i]); 1803a7267d53Smartin l->func = found_fs_nocheck; 1804a7267d53Smartin l++; 1805a7267d53Smartin } 1806a7267d53Smartin assert((size_t)(l - fstabbuf) == num_entries); 180750dbef1aSdholland 180850dbef1aSdholland /* First the root device. */ 180950dbef1aSdholland if (target_already_root()) 181050dbef1aSdholland /* avoid needing to call target_already_root() again */ 181150dbef1aSdholland targetroot_mnt[0] = 0; 181250dbef1aSdholland else { 1813c2ed2005Smartin for (i = 0; i < install->num; i++) { 1814c2ed2005Smartin if (is_root_part_mount(install->infos[i].mount)) 1815c2ed2005Smartin break; 1816c2ed2005Smartin } 1817c2ed2005Smartin 1818c2ed2005Smartin if (i >= install->num) { 1819c2ed2005Smartin hit_enter_to_continue(MSG_noroot, NULL); 1820c2ed2005Smartin return -1; 1821c2ed2005Smartin } 1822c2ed2005Smartin 1823c2ed2005Smartin if (!install->infos[i].parts->pscheme->get_part_device( 1824c2ed2005Smartin install->infos[i].parts, install->infos[i].cur_part_id, 18254103857bSmartin devdev, sizeof devdev, NULL, plain_name, true)) 18264103857bSmartin return -1; 1827a7267d53Smartin error = mount_root(devdev, true, false, install); 182850dbef1aSdholland if (error != 0 && error != EBUSY) 182950dbef1aSdholland return -1; 183050dbef1aSdholland } 183150dbef1aSdholland 183250dbef1aSdholland /* Check the target /etc/fstab exists before trying to parse it. */ 183350dbef1aSdholland if (target_dir_exists_p("/etc") == 0 || 183450dbef1aSdholland target_file_exists_p("/etc/fstab") == 0) { 183524ecf24eSchristos msg_fmt_display(MSG_noetcfstab, "%s", pm->diskdev); 18364103857bSmartin hit_enter_to_continue(NULL, NULL); 183750dbef1aSdholland return -1; 183850dbef1aSdholland } 183950dbef1aSdholland 184050dbef1aSdholland 184150dbef1aSdholland /* Get fstab entries from the target-root /etc/fstab. */ 184250dbef1aSdholland fstabsize = target_collect_file(T_FILE, &fstab, "/etc/fstab"); 184350dbef1aSdholland if (fstabsize < 0) { 184450dbef1aSdholland /* error ! */ 184524ecf24eSchristos msg_fmt_display(MSG_badetcfstab, "%s", pm->diskdev); 18464103857bSmartin hit_enter_to_continue(NULL, NULL); 1847a7267d53Smartin umount_root(); 18484b2364d9Smartin return -2; 184950dbef1aSdholland } 1850a7267d53Smartin /* 1851a7267d53Smartin * We unmount the read-only root again, so we can mount it 1852a7267d53Smartin * with proper options from /etc/fstab 1853a7267d53Smartin */ 1854a7267d53Smartin umount_root(); 1855a7267d53Smartin 1856a7267d53Smartin /* 1857a7267d53Smartin * Now do all entries in /etc/fstab and mount them if required 1858a7267d53Smartin */ 1859a7267d53Smartin error = walk(fstab, (size_t)fstabsize, fstabbuf, num_entries); 186050dbef1aSdholland free(fstab); 1861a7267d53Smartin for (i = 0; i < num_entries; i++) 1862a7267d53Smartin free(__UNCONST(fstabbuf[i].fmt)); 1863a7267d53Smartin free(fstabbuf); 186450dbef1aSdholland 186550dbef1aSdholland return error; 186650dbef1aSdholland } 186750dbef1aSdholland 186850dbef1aSdholland int 18694103857bSmartin set_swap_if_low_ram(struct install_partition_desc *install) 1870bbeaff62Sisaki { 187140a37f0dSabs if (get_ramsize() <= 32) 18724103857bSmartin return set_swap(install); 187340a37f0dSabs return 0; 187440a37f0dSabs } 187540a37f0dSabs 187640a37f0dSabs int 18774103857bSmartin set_swap(struct install_partition_desc *install) 187850dbef1aSdholland { 18794103857bSmartin size_t i; 18804103857bSmartin char dev_buf[PATH_MAX]; 188150dbef1aSdholland int rval; 188250dbef1aSdholland 18834103857bSmartin for (i = 0; i < install->num; i++) { 18844103857bSmartin if (install->infos[i].type == PT_swap) 18854103857bSmartin break; 18864103857bSmartin } 18874103857bSmartin if (i >= install->num) 18884103857bSmartin return 0; 188950dbef1aSdholland 18904103857bSmartin if (!install->infos[i].parts->pscheme->get_part_device( 18914103857bSmartin install->infos[i].parts, install->infos[i].cur_part_id, dev_buf, 18924103857bSmartin sizeof dev_buf, NULL, plain_name, true)) 18934103857bSmartin return -1; 18944103857bSmartin 18954103857bSmartin rval = swapctl(SWAP_ON, dev_buf, 0); 189650dbef1aSdholland if (rval != 0) 189750dbef1aSdholland return -1; 189850dbef1aSdholland 189950dbef1aSdholland return 0; 190050dbef1aSdholland } 190150dbef1aSdholland 190250dbef1aSdholland int 190350dbef1aSdholland check_swap(const char *disk, int remove_swap) 190450dbef1aSdholland { 190550dbef1aSdholland struct swapent *swap; 190650dbef1aSdholland char *cp; 190750dbef1aSdholland int nswap; 190850dbef1aSdholland int l; 190950dbef1aSdholland int rval = 0; 191050dbef1aSdholland 191150dbef1aSdholland nswap = swapctl(SWAP_NSWAP, 0, 0); 191250dbef1aSdholland if (nswap <= 0) 191350dbef1aSdholland return 0; 191450dbef1aSdholland 191550dbef1aSdholland swap = malloc(nswap * sizeof *swap); 191650dbef1aSdholland if (swap == NULL) 191750dbef1aSdholland return -1; 191850dbef1aSdholland 191950dbef1aSdholland nswap = swapctl(SWAP_STATS, swap, nswap); 192050dbef1aSdholland if (nswap < 0) 192150dbef1aSdholland goto bad_swap; 192250dbef1aSdholland 192350dbef1aSdholland l = strlen(disk); 192450dbef1aSdholland while (--nswap >= 0) { 192550dbef1aSdholland /* Should we check the se_dev or se_path? */ 192650dbef1aSdholland cp = swap[nswap].se_path; 192750dbef1aSdholland if (memcmp(cp, "/dev/", 5) != 0) 192850dbef1aSdholland continue; 192950dbef1aSdholland if (memcmp(cp + 5, disk, l) != 0) 193050dbef1aSdholland continue; 193150dbef1aSdholland if (!isalpha(*(unsigned char *)(cp + 5 + l))) 193250dbef1aSdholland continue; 193350dbef1aSdholland if (cp[5 + l + 1] != 0) 193450dbef1aSdholland continue; 193550dbef1aSdholland /* ok path looks like it is for this device */ 193650dbef1aSdholland if (!remove_swap) { 193750dbef1aSdholland /* count active swap areas */ 193850dbef1aSdholland rval++; 193950dbef1aSdholland continue; 194050dbef1aSdholland } 194150dbef1aSdholland if (swapctl(SWAP_OFF, cp, 0) == -1) 194250dbef1aSdholland rval = -1; 194350dbef1aSdholland } 194450dbef1aSdholland 194550dbef1aSdholland done: 194650dbef1aSdholland free(swap); 194750dbef1aSdholland return rval; 194850dbef1aSdholland 194950dbef1aSdholland bad_swap: 195050dbef1aSdholland rval = -1; 195150dbef1aSdholland goto done; 195250dbef1aSdholland } 195350dbef1aSdholland 195450dbef1aSdholland #ifdef HAVE_BOOTXX_xFS 195550dbef1aSdholland char * 19564103857bSmartin bootxx_name(struct install_partition_desc *install) 195750dbef1aSdholland { 195850dbef1aSdholland int fstype; 195950dbef1aSdholland const char *bootxxname; 196050dbef1aSdholland char *bootxx; 196150dbef1aSdholland 196250dbef1aSdholland /* check we have boot code for the root partition type */ 19634103857bSmartin fstype = install->infos[0].fs_type; 196450dbef1aSdholland switch (fstype) { 196550dbef1aSdholland #if defined(BOOTXX_FFSV1) || defined(BOOTXX_FFSV2) 196650dbef1aSdholland case FS_BSDFFS: 19674103857bSmartin if (install->infos[0].fs_version == 2) { 196850dbef1aSdholland #ifdef BOOTXX_FFSV2 196950dbef1aSdholland bootxxname = BOOTXX_FFSV2; 197050dbef1aSdholland #else 197150dbef1aSdholland bootxxname = NULL; 197250dbef1aSdholland #endif 197350dbef1aSdholland } else { 197450dbef1aSdholland #ifdef BOOTXX_FFSV1 197550dbef1aSdholland bootxxname = BOOTXX_FFSV1; 197650dbef1aSdholland #else 197750dbef1aSdholland bootxxname = NULL; 197850dbef1aSdholland #endif 197950dbef1aSdholland } 198050dbef1aSdholland break; 198150dbef1aSdholland #endif 19827935b6fcSpgoyette #ifdef BOOTXX_LFSV2 198350dbef1aSdholland case FS_BSDLFS: 19847935b6fcSpgoyette bootxxname = BOOTXX_LFSV2; 198550dbef1aSdholland break; 198650dbef1aSdholland #endif 198750dbef1aSdholland default: 198850dbef1aSdholland bootxxname = NULL; 198950dbef1aSdholland break; 199050dbef1aSdholland } 199150dbef1aSdholland 199250dbef1aSdholland if (bootxxname == NULL) 199350dbef1aSdholland return NULL; 199450dbef1aSdholland 199550dbef1aSdholland asprintf(&bootxx, "%s/%s", BOOTXXDIR, bootxxname); 199650dbef1aSdholland return bootxx; 199750dbef1aSdholland } 199850dbef1aSdholland #endif 19994b2364d9Smartin 20004b2364d9Smartin /* from dkctl.c */ 20014b2364d9Smartin static int 20024b2364d9Smartin get_dkwedges_sort(const void *a, const void *b) 20034b2364d9Smartin { 20044b2364d9Smartin const struct dkwedge_info *dkwa = a, *dkwb = b; 20054b2364d9Smartin const daddr_t oa = dkwa->dkw_offset, ob = dkwb->dkw_offset; 20064b2364d9Smartin return (oa < ob) ? -1 : (oa > ob) ? 1 : 0; 20074b2364d9Smartin } 20084b2364d9Smartin 20094b2364d9Smartin int 20104b2364d9Smartin get_dkwedges(struct dkwedge_info **dkw, const char *diskdev) 20114b2364d9Smartin { 20124b2364d9Smartin struct dkwedge_list dkwl; 20134b2364d9Smartin 20144b2364d9Smartin *dkw = NULL; 201572ea5dbaSchristos if (!get_wedge_list(diskdev, &dkwl)) 20164b2364d9Smartin return -1; 20174b2364d9Smartin 201872ea5dbaSchristos if (dkwl.dkwl_nwedges > 0 && *dkw != NULL) { 201972ea5dbaSchristos qsort(*dkw, dkwl.dkwl_nwedges, sizeof(**dkw), 202072ea5dbaSchristos get_dkwedges_sort); 20214b2364d9Smartin } 20224b2364d9Smartin 20234b2364d9Smartin return dkwl.dkwl_nwedges; 20244b2364d9Smartin } 2025