1*050294faShannken /* $NetBSD: util.c,v 1.77 2024/04/25 11:25:08 hannken 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 /* util.c -- routines that don't really fit anywhere else... */
3650dbef1aSdholland
37ac730b51Smartin #include <assert.h>
38ac730b51Smartin #include <inttypes.h>
3950dbef1aSdholland #include <stdio.h>
4050dbef1aSdholland #include <stdarg.h>
4150dbef1aSdholland #include <string.h>
4250dbef1aSdholland #include <unistd.h>
4350dbef1aSdholland #include <sys/mount.h>
4450dbef1aSdholland #include <sys/dkio.h>
4550dbef1aSdholland #include <sys/ioctl.h>
4650dbef1aSdholland #include <sys/types.h>
4750dbef1aSdholland #include <sys/param.h>
4850dbef1aSdholland #include <sys/sysctl.h>
4950dbef1aSdholland #include <sys/stat.h>
5050dbef1aSdholland #include <sys/statvfs.h>
5150dbef1aSdholland #include <isofs/cd9660/iso.h>
5250dbef1aSdholland #include <curses.h>
5350dbef1aSdholland #include <err.h>
5450dbef1aSdholland #include <errno.h>
5550dbef1aSdholland #include <dirent.h>
5650dbef1aSdholland #include <util.h>
5750dbef1aSdholland #include "defs.h"
5850dbef1aSdholland #include "md.h"
594103857bSmartin #include "defsizes.h"
6050dbef1aSdholland #include "msg_defs.h"
6150dbef1aSdholland #include "menu_defs.h"
62249ed7a6Smartin #ifdef MD_MAY_SWAP_TO
63249ed7a6Smartin #include <sys/drvctlio.h>
64249ed7a6Smartin #endif
65043e812bSmartin #ifdef CHECK_ENTROPY
66043e812bSmartin #include <sha2.h>
67043e812bSmartin #include <paths.h>
68043e812bSmartin #endif
6950dbef1aSdholland
7050dbef1aSdholland #define MAX_CD_DEVS 256 /* how many cd drives do we expect to attach */
7150dbef1aSdholland #define ISO_BLKSIZE ISO_DEFAULT_BLOCK_SIZE
7250dbef1aSdholland
7350dbef1aSdholland static const char *msg_yes, *msg_no, *msg_all, *msg_some, *msg_none;
7450dbef1aSdholland static int select_menu_width;
7550dbef1aSdholland
76fe2acef4Schristos static uint8_t set_status[SET_GROUP_END];
7750dbef1aSdholland #define SET_VALID 0x01
7850dbef1aSdholland #define SET_SELECTED 0x02
7950dbef1aSdholland #define SET_SKIPPED 0x04
8050dbef1aSdholland #define SET_INSTALLED 0x08
81249ed7a6Smartin #define SET_NO_EXTRACT 0x10
8250dbef1aSdholland
8350dbef1aSdholland struct tarstats {
8450dbef1aSdholland int nselected;
8550dbef1aSdholland int nfound;
8650dbef1aSdholland int nnotfound;
8750dbef1aSdholland int nerror;
8850dbef1aSdholland int nsuccess;
8950dbef1aSdholland int nskipped;
9050dbef1aSdholland } tarstats;
9150dbef1aSdholland
9250dbef1aSdholland distinfo dist_list[] = {
9350dbef1aSdholland #ifdef SET_KERNEL_1_NAME
940ef20e92Smartin {SET_KERNEL_1_NAME, SET_KERNEL_1, false, MSG_set_kernel_1, NULL},
9550dbef1aSdholland #endif
9650dbef1aSdholland #ifdef SET_KERNEL_2_NAME
970ef20e92Smartin {SET_KERNEL_2_NAME, SET_KERNEL_2, false, MSG_set_kernel_2, NULL},
9850dbef1aSdholland #endif
9950dbef1aSdholland #ifdef SET_KERNEL_3_NAME
1000ef20e92Smartin {SET_KERNEL_3_NAME, SET_KERNEL_3, false, MSG_set_kernel_3, NULL},
10150dbef1aSdholland #endif
10250dbef1aSdholland #ifdef SET_KERNEL_4_NAME
1030ef20e92Smartin {SET_KERNEL_4_NAME, SET_KERNEL_4, false, MSG_set_kernel_4, NULL},
10450dbef1aSdholland #endif
10550dbef1aSdholland #ifdef SET_KERNEL_5_NAME
1060ef20e92Smartin {SET_KERNEL_5_NAME, SET_KERNEL_5, false, MSG_set_kernel_5, NULL},
10750dbef1aSdholland #endif
10850dbef1aSdholland #ifdef SET_KERNEL_6_NAME
1090ef20e92Smartin {SET_KERNEL_6_NAME, SET_KERNEL_6, false, MSG_set_kernel_6, NULL},
11050dbef1aSdholland #endif
11150dbef1aSdholland #ifdef SET_KERNEL_7_NAME
1120ef20e92Smartin {SET_KERNEL_7_NAME, SET_KERNEL_7, false, MSG_set_kernel_7, NULL},
11350dbef1aSdholland #endif
11450dbef1aSdholland #ifdef SET_KERNEL_8_NAME
1150ef20e92Smartin {SET_KERNEL_8_NAME, SET_KERNEL_8, false, MSG_set_kernel_8, NULL},
11650dbef1aSdholland #endif
11750dbef1aSdholland #ifdef SET_KERNEL_9_NAME
1180ef20e92Smartin {SET_KERNEL_9_NAME, SET_KERNEL_9, false, MSG_set_kernel_9, NULL},
11950dbef1aSdholland #endif
12050dbef1aSdholland
121bfb6e561Smartin #ifdef HAVE_MODULES
1220ef20e92Smartin {"modules", SET_MODULES, false, MSG_set_modules, NULL},
123bfb6e561Smartin #endif
1240ef20e92Smartin {"base", SET_BASE, false, MSG_set_base, NULL},
125545236f4Snia #ifdef HAVE_BASE32
126545236f4Snia {"base32", SET_BASE32, false, MSG_set_base32, NULL},
127545236f4Snia #endif
128f7dfb798Snia #ifdef HAVE_BASE64
129f7dfb798Snia {"base64", SET_BASE64, false, MSG_set_base64, NULL},
130f7dfb798Snia #endif
131043d88a7Sjmcneill #ifdef HAVE_DTB
132043d88a7Sjmcneill {"dtb", SET_DTB, false, MSG_set_dtb, NULL},
133043d88a7Sjmcneill #endif
1340ef20e92Smartin {"etc", SET_ETC, false, MSG_set_system, NULL},
1350ef20e92Smartin {"comp", SET_COMPILER, false, MSG_set_compiler, NULL},
1360ef20e92Smartin {"games", SET_GAMES, false, MSG_set_games, NULL},
137f54624bdSmaya {"gpufw", SET_GPUFW, false, MSG_set_gpufw, NULL},
1380ef20e92Smartin {"man", SET_MAN_PAGES, false, MSG_set_man_pages, NULL},
139545236f4Snia {"manhtml", SET_MAN_PAGES_HTML, false, MSG_set_man_pages_html, NULL},
1400ef20e92Smartin {"misc", SET_MISC, false, MSG_set_misc, NULL},
14150f74585Smaya {"rescue", SET_RESCUE, false, MSG_set_rescue, NULL},
1420ef20e92Smartin {"tests", SET_TESTS, false, MSG_set_tests, NULL},
1430ef20e92Smartin {"text", SET_TEXT_TOOLS, false, MSG_set_text_tools, NULL},
14450dbef1aSdholland
1450ef20e92Smartin {NULL, SET_GROUP, false, MSG_set_X11, NULL},
1460ef20e92Smartin {"xbase", SET_X11_BASE, false, MSG_set_X11_base, NULL},
1470ef20e92Smartin {"xcomp", SET_X11_PROG, false, MSG_set_X11_prog, NULL},
1480ef20e92Smartin {"xetc", SET_X11_ETC, false, MSG_set_X11_etc, NULL},
1490ef20e92Smartin {"xfont", SET_X11_FONTS, false, MSG_set_X11_fonts, NULL},
1500ef20e92Smartin {"xserver", SET_X11_SERVERS, false, MSG_set_X11_servers, NULL},
1510ef20e92Smartin {NULL, SET_GROUP_END, false, NULL, NULL},
15250dbef1aSdholland
15350dbef1aSdholland #ifdef SET_MD_1_NAME
1540ef20e92Smartin {SET_MD_1_NAME, SET_MD_1, false, MSG_set_md_1, NULL},
15550dbef1aSdholland #endif
15650dbef1aSdholland #ifdef SET_MD_2_NAME
1570ef20e92Smartin {SET_MD_2_NAME, SET_MD_2, false, MSG_set_md_2, NULL},
15850dbef1aSdholland #endif
15950dbef1aSdholland #ifdef SET_MD_3_NAME
1600ef20e92Smartin {SET_MD_3_NAME, SET_MD_3, false, MSG_set_md_3, NULL},
16150dbef1aSdholland #endif
16250dbef1aSdholland #ifdef SET_MD_4_NAME
1630ef20e92Smartin {SET_MD_4_NAME, SET_MD_4, false, MSG_set_md_4, NULL},
16450dbef1aSdholland #endif
16550dbef1aSdholland
1660ef20e92Smartin {NULL, SET_GROUP, true, MSG_set_source, NULL},
1670ef20e92Smartin {"syssrc", SET_SYSSRC, true, MSG_set_syssrc, NULL},
1680ef20e92Smartin {"src", SET_SRC, true, MSG_set_src, NULL},
1690ef20e92Smartin {"sharesrc", SET_SHARESRC, true, MSG_set_sharesrc, NULL},
1700ef20e92Smartin {"gnusrc", SET_GNUSRC, true, MSG_set_gnusrc, NULL},
1710ef20e92Smartin {"xsrc", SET_XSRC, true, MSG_set_xsrc, NULL},
1720ef20e92Smartin {"debug", SET_DEBUG, false, MSG_set_debug, NULL},
173545236f4Snia #ifdef HAVE_DEBUG32
174545236f4Snia {"debug32", SET_DEBUG32, false, MSG_set_debug32, NULL},
175545236f4Snia #endif
176f7dfb798Snia #ifdef HAVE_DEBUG64
177f7dfb798Snia {"debug64", SET_DEBUG64, false, MSG_set_debug64, NULL},
178f7dfb798Snia #endif
1790ef20e92Smartin {"xdebug", SET_X11_DEBUG, false, MSG_set_xdebug, NULL},
1800ef20e92Smartin {NULL, SET_GROUP_END, false, NULL, NULL},
18150dbef1aSdholland
1820ef20e92Smartin {NULL, SET_LAST, false, NULL, NULL},
18350dbef1aSdholland };
18450dbef1aSdholland
18550dbef1aSdholland #define MAX_CD_INFOS 16 /* how many media can be found? */
18650dbef1aSdholland struct cd_info {
18750dbef1aSdholland char device_name[16];
18850dbef1aSdholland char menu[100];
18950dbef1aSdholland };
19050dbef1aSdholland static struct cd_info cds[MAX_CD_INFOS];
19150dbef1aSdholland
1924103857bSmartin /* flags whether to offer the respective options (depending on helper
1934103857bSmartin programs available on install media */
1944103857bSmartin int have_raid, have_vnd, have_cgd, have_lvm, have_gpt, have_dk;
1954103857bSmartin
19650dbef1aSdholland /*
19750dbef1aSdholland * local prototypes
19850dbef1aSdholland */
19950dbef1aSdholland
20050dbef1aSdholland static int check_for(unsigned int mode, const char *pathname);
201ea2cbdfdSmrg static int get_iso9660_volname(int dev, int sess, char *volname,
202ea2cbdfdSmrg size_t volnamelen);
20350dbef1aSdholland static int get_available_cds(void);
2044103857bSmartin static int binary_available(const char *prog);
20550dbef1aSdholland
20650dbef1aSdholland void
init_set_status(int flags)20750dbef1aSdholland init_set_status(int flags)
20850dbef1aSdholland {
20950dbef1aSdholland static const uint8_t sets_valid[] = {MD_SETS_VALID};
21050dbef1aSdholland static const uint8_t sets_selected_full[] = {MD_SETS_SELECTED};
21150dbef1aSdholland static const uint8_t sets_selected_minimal[] = {MD_SETS_SELECTED_MINIMAL};
21250dbef1aSdholland static const uint8_t sets_selected_nox[] = {MD_SETS_SELECTED_NOX};
21350dbef1aSdholland static const uint8_t *sets_selected;
21450dbef1aSdholland unsigned int nelem_selected;
21550dbef1aSdholland unsigned int i, len;
21650dbef1aSdholland const char *longest;
21750dbef1aSdholland
21850dbef1aSdholland if (flags & SFLAG_MINIMAL) {
21950dbef1aSdholland sets_selected = sets_selected_minimal;
2204103857bSmartin nelem_selected = __arraycount(sets_selected_minimal);
22150dbef1aSdholland } else if (flags & SFLAG_NOX) {
22250dbef1aSdholland sets_selected = sets_selected_nox;
2234103857bSmartin nelem_selected = __arraycount(sets_selected_nox);
22450dbef1aSdholland } else {
22550dbef1aSdholland sets_selected = sets_selected_full;
2264103857bSmartin nelem_selected = __arraycount(sets_selected_full);
22750dbef1aSdholland }
22850dbef1aSdholland
2294103857bSmartin for (i = 0; i < __arraycount(sets_valid); i++)
23050dbef1aSdholland set_status[sets_valid[i]] = SET_VALID;
23150dbef1aSdholland for (i = 0; i < nelem_selected; i++)
23250dbef1aSdholland set_status[sets_selected[i]] |= SET_SELECTED;
23350dbef1aSdholland
23450dbef1aSdholland set_status[SET_GROUP] = SET_VALID;
23550dbef1aSdholland
23650dbef1aSdholland /* Lookup some strings we need lots of times */
23750dbef1aSdholland msg_yes = msg_string(MSG_Yes);
23850dbef1aSdholland msg_no = msg_string(MSG_No);
23950dbef1aSdholland msg_all = msg_string(MSG_All);
24050dbef1aSdholland msg_some = msg_string(MSG_Some);
24150dbef1aSdholland msg_none = msg_string(MSG_None);
24250dbef1aSdholland
24350dbef1aSdholland /* Find longest and use it to determine width of selection menu */
24450dbef1aSdholland len = strlen(msg_no); longest = msg_no;
24550dbef1aSdholland i = strlen(msg_yes); if (i > len) {len = i; longest = msg_yes; }
24650dbef1aSdholland i = strlen(msg_all); if (i > len) {len = i; longest = msg_all; }
24750dbef1aSdholland i = strlen(msg_some); if (i > len) {len = i; longest = msg_some; }
24850dbef1aSdholland i = strlen(msg_none); if (i > len) {len = i; longest = msg_none; }
249*050294faShannken select_menu_width = snprintf(NULL, 0, "%-40s %s", "", longest);
25050dbef1aSdholland
25150dbef1aSdholland /* Give the md code a chance to choose the right kernel, etc. */
25250dbef1aSdholland md_init_set_status(flags);
25350dbef1aSdholland }
25450dbef1aSdholland
25550dbef1aSdholland int
dir_exists_p(const char * path)25650dbef1aSdholland dir_exists_p(const char *path)
25750dbef1aSdholland {
25850dbef1aSdholland
25950dbef1aSdholland return file_mode_match(path, S_IFDIR);
26050dbef1aSdholland }
26150dbef1aSdholland
26250dbef1aSdholland int
file_exists_p(const char * path)26350dbef1aSdholland file_exists_p(const char *path)
26450dbef1aSdholland {
26550dbef1aSdholland
26650dbef1aSdholland return file_mode_match(path, S_IFREG);
26750dbef1aSdholland }
26850dbef1aSdholland
26950dbef1aSdholland int
file_mode_match(const char * path,unsigned int mode)27050dbef1aSdholland file_mode_match(const char *path, unsigned int mode)
27150dbef1aSdholland {
27250dbef1aSdholland struct stat st;
27350dbef1aSdholland
27450dbef1aSdholland return (stat(path, &st) == 0 && (st.st_mode & S_IFMT) == mode);
27550dbef1aSdholland }
27650dbef1aSdholland
2774103857bSmartin /* return ram size in MB */
2784103857bSmartin uint64_t
get_ramsize(void)27950dbef1aSdholland get_ramsize(void)
28050dbef1aSdholland {
28164e2b749Smartin static uint64_t ramsize;
28264e2b749Smartin
28364e2b749Smartin if (ramsize == 0) {
28450dbef1aSdholland size_t len = sizeof ramsize;
28550dbef1aSdholland int mib[2] = {CTL_HW, HW_PHYSMEM64};
28650dbef1aSdholland
28750dbef1aSdholland sysctl(mib, 2, &ramsize, &len, NULL, 0);
28864e2b749Smartin }
28950dbef1aSdholland
29050dbef1aSdholland /* Find out how many Megs ... round up. */
29150dbef1aSdholland return (ramsize + MEG - 1) / MEG;
29250dbef1aSdholland }
29350dbef1aSdholland
29450dbef1aSdholland void
run_makedev(void)29550dbef1aSdholland run_makedev(void)
29650dbef1aSdholland {
29750dbef1aSdholland char *owd;
29850dbef1aSdholland
29950dbef1aSdholland msg_display_add("\n\n");
30050dbef1aSdholland msg_display_add(MSG_makedev);
30150dbef1aSdholland
30250dbef1aSdholland owd = getcwd(NULL, 0);
30350dbef1aSdholland
30450dbef1aSdholland /* make /dev, in case the user didn't extract it. */
30550dbef1aSdholland make_target_dir("/dev");
30650dbef1aSdholland target_chdir_or_die("/dev");
30750dbef1aSdholland run_program(0, "/bin/sh MAKEDEV all");
30850dbef1aSdholland
30950dbef1aSdholland chdir(owd);
31050dbef1aSdholland free(owd);
31150dbef1aSdholland }
31250dbef1aSdholland
31350dbef1aSdholland /*
31450dbef1aSdholland * Performs in-place replacement of a set of patterns in a file that lives
31550dbef1aSdholland * inside the installed system. The patterns must be separated by a semicolon.
31650dbef1aSdholland * For example:
31750dbef1aSdholland *
31850dbef1aSdholland * replace("/etc/some-file.conf", "s/prop1=NO/prop1=YES/;s/foo/bar/");
31950dbef1aSdholland */
32050dbef1aSdholland void
replace(const char * path,const char * patterns,...)32150dbef1aSdholland replace(const char *path, const char *patterns, ...)
32250dbef1aSdholland {
32350dbef1aSdholland char *spatterns;
32450dbef1aSdholland va_list ap;
32550dbef1aSdholland
32650dbef1aSdholland va_start(ap, patterns);
32750dbef1aSdholland vasprintf(&spatterns, patterns, ap);
32850dbef1aSdholland va_end(ap);
32950dbef1aSdholland if (spatterns == NULL)
33050dbef1aSdholland err(1, "vasprintf(&spatterns, \"%s\", ...)", patterns);
33150dbef1aSdholland
33250dbef1aSdholland run_program(RUN_CHROOT, "sed -an -e '%s;H;$!d;g;w %s' %s", spatterns,
33350dbef1aSdholland path, path);
33450dbef1aSdholland
33550dbef1aSdholland free(spatterns);
33650dbef1aSdholland }
33750dbef1aSdholland
33850dbef1aSdholland static int
floppy_fetch(const char * set_name)33950dbef1aSdholland floppy_fetch(const char *set_name)
34050dbef1aSdholland {
34150dbef1aSdholland char post[4];
34250dbef1aSdholland msg errmsg;
34350dbef1aSdholland int menu;
34450dbef1aSdholland int status;
34550dbef1aSdholland const char *write_mode = ">";
34650dbef1aSdholland
34750dbef1aSdholland strcpy(post, "aa");
34850dbef1aSdholland
34950dbef1aSdholland errmsg = "";
35050dbef1aSdholland menu = MENU_fdok;
35150dbef1aSdholland for (;;) {
35250dbef1aSdholland umount_mnt2();
35350dbef1aSdholland msg_display(errmsg);
35424ecf24eSchristos msg_fmt_display_add(MSG_fdmount, "%s%s", set_name, post);
35550dbef1aSdholland process_menu(menu, &status);
35650dbef1aSdholland if (status != SET_CONTINUE)
35750dbef1aSdholland return status;
35850dbef1aSdholland menu = MENU_fdremount;
35950dbef1aSdholland errmsg = MSG_fdremount;
36050dbef1aSdholland if (run_program(0, "/sbin/mount -r -t %s %s /mnt2",
36150dbef1aSdholland fd_type, fd_dev))
36250dbef1aSdholland continue;
36350dbef1aSdholland mnt2_mounted = 1;
36450dbef1aSdholland errmsg = MSG_fdnotfound;
36550dbef1aSdholland
36650dbef1aSdholland /* Display this because it might take a while.... */
36750dbef1aSdholland if (run_program(RUN_DISPLAY,
36850dbef1aSdholland "sh -c '/bin/cat /mnt2/%s.%s %s %s/%s/%s%s'",
36950dbef1aSdholland set_name, post, write_mode,
3700ef20e92Smartin target_prefix(), xfer_dir, set_name,
3710ef20e92Smartin set_postfix(set_name)))
37250dbef1aSdholland /* XXX: a read error will give a corrupt file! */
37350dbef1aSdholland continue;
37450dbef1aSdholland
37550dbef1aSdholland /* We got that file, advance to next fragment */
37650dbef1aSdholland if (post[1] < 'z')
37750dbef1aSdholland post[1]++;
37850dbef1aSdholland else
37950dbef1aSdholland post[1] = 'a', post[0]++;
38050dbef1aSdholland write_mode = ">>";
38150dbef1aSdholland errmsg = "";
38250dbef1aSdholland menu = MENU_fdok;
38350dbef1aSdholland }
38450dbef1aSdholland }
38550dbef1aSdholland
38650dbef1aSdholland /*
38750dbef1aSdholland * Load files from floppy. Requires a /mnt2 directory for mounting them.
38850dbef1aSdholland */
38950dbef1aSdholland int
get_via_floppy(void)39050dbef1aSdholland get_via_floppy(void)
39150dbef1aSdholland {
392e21052b4Smartin int rv = -1;
393e21052b4Smartin
394e21052b4Smartin process_menu(MENU_floppysource, &rv);
395e21052b4Smartin if (rv == SET_RETRY)
3964b2364d9Smartin return SET_RETRY;
39750dbef1aSdholland
39850dbef1aSdholland fetch_fn = floppy_fetch;
39950dbef1aSdholland
40050dbef1aSdholland /* Set ext_dir for absolute path. */
40150dbef1aSdholland snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s", target_prefix(), xfer_dir);
40250dbef1aSdholland snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s", target_prefix(), xfer_dir);
40350dbef1aSdholland
40450dbef1aSdholland return SET_OK;
40550dbef1aSdholland }
40650dbef1aSdholland
40750dbef1aSdholland /*
40850dbef1aSdholland * Get the volume name of a ISO9660 file system
40950dbef1aSdholland */
41050dbef1aSdholland static int
get_iso9660_volname(int dev,int sess,char * volname,size_t volnamelen)411ea2cbdfdSmrg get_iso9660_volname(int dev, int sess, char *volname, size_t volnamelen)
41250dbef1aSdholland {
41350dbef1aSdholland int blkno, error, last;
414a018a4a9Smartin static char buf[ISO_BLKSIZE] __aligned(8);
41550dbef1aSdholland struct iso_volume_descriptor *vd = NULL;
41650dbef1aSdholland struct iso_primary_descriptor *pd = NULL;
41750dbef1aSdholland
41850dbef1aSdholland for (blkno = sess+16; blkno < sess+16+100; blkno++) {
41950dbef1aSdholland error = pread(dev, buf, ISO_BLKSIZE, blkno*ISO_BLKSIZE);
42050dbef1aSdholland if (error == -1)
42150dbef1aSdholland return -1;
42250dbef1aSdholland vd = (struct iso_volume_descriptor *)&buf;
42350dbef1aSdholland if (memcmp(vd->id, ISO_STANDARD_ID, sizeof(vd->id)) != 0)
42450dbef1aSdholland return -1;
42550dbef1aSdholland if (isonum_711((const unsigned char *)&vd->type)
42650dbef1aSdholland == ISO_VD_PRIMARY) {
42750dbef1aSdholland pd = (struct iso_primary_descriptor*)buf;
428ea2cbdfdSmrg strncpy(volname, pd->volume_id, volnamelen - 1);
429ea2cbdfdSmrg volname[volnamelen - 1] = '\0';
430ea2cbdfdSmrg last = volnamelen - 1;
43150dbef1aSdholland while (last >= 0
43250dbef1aSdholland && (volname[last] == ' ' || volname[last] == 0))
43350dbef1aSdholland last--;
43450dbef1aSdholland volname[last+1] = 0;
43550dbef1aSdholland return 0;
43650dbef1aSdholland }
43750dbef1aSdholland }
43850dbef1aSdholland return -1;
43950dbef1aSdholland }
44050dbef1aSdholland
44150dbef1aSdholland /*
4421c2e5b02Smartin * Local state while iterating CDs and collecting volumes
44350dbef1aSdholland */
4441c2e5b02Smartin struct get_available_cds_state {
44504645caaSmartin size_t num_mounted;
44604645caaSmartin struct statvfs *mounted;
4471c2e5b02Smartin struct cd_info *info;
4481c2e5b02Smartin size_t count;
4491c2e5b02Smartin };
45050dbef1aSdholland
4511c2e5b02Smartin /*
4521c2e5b02Smartin * Callback function: if this is a CD, enumerate all volumes on it
4531c2e5b02Smartin */
4541c2e5b02Smartin static bool
get_available_cds_helper(void * arg,const char * device)4551c2e5b02Smartin get_available_cds_helper(void *arg, const char *device)
4561c2e5b02Smartin {
4571c2e5b02Smartin struct get_available_cds_state *state = arg;
45804645caaSmartin char dname[16], tname[16], volname[80], *t;
4591c2e5b02Smartin struct disklabel label;
46004645caaSmartin int part, dev, error, sess, ready, tlen;
4611c2e5b02Smartin
46257cf8237Smartin if (!is_cdrom_device(device, false))
4631c2e5b02Smartin return true;
4641c2e5b02Smartin
4651c2e5b02Smartin sprintf(dname, "/dev/r%s%c", device, 'a'+RAW_PART);
46604645caaSmartin tlen = sprintf(tname, "/dev/%s", device);
46704645caaSmartin
46804645caaSmartin /* check if this is mounted already */
46904645caaSmartin for (size_t i = 0; i < state->num_mounted; i++) {
47004645caaSmartin if (strncmp(state->mounted[i].f_mntfromname, tname, tlen)
47104645caaSmartin == 0) {
47204645caaSmartin t = state->mounted[i].f_mntfromname + tlen;
47304645caaSmartin if (t[0] >= 'a' && t[0] <= 'z' && t[1] == 0)
47404645caaSmartin return true;
47504645caaSmartin }
47604645caaSmartin }
47704645caaSmartin
47850dbef1aSdholland dev = open(dname, O_RDONLY, 0);
47950dbef1aSdholland if (dev == -1)
4801c2e5b02Smartin return true;
4811c2e5b02Smartin
48250dbef1aSdholland ready = 0;
48350dbef1aSdholland error = ioctl(dev, DIOCTUR, &ready);
48450dbef1aSdholland if (error != 0 || ready == 0) {
48550dbef1aSdholland close(dev);
4861c2e5b02Smartin return true;
48750dbef1aSdholland }
48850dbef1aSdholland error = ioctl(dev, DIOCGDINFO, &label);
48950dbef1aSdholland close(dev);
4901c2e5b02Smartin if (error != 0)
4911c2e5b02Smartin return true;
4921c2e5b02Smartin
4931c2e5b02Smartin for (part = 0; part < label.d_npartitions; part++) {
4941c2e5b02Smartin
4951c2e5b02Smartin if (label.d_partitions[part].p_fstype == FS_UNUSED
49650dbef1aSdholland || label.d_partitions[part].p_size == 0)
49750dbef1aSdholland continue;
4981c2e5b02Smartin
4991c2e5b02Smartin if (label.d_partitions[part].p_fstype == FS_ISO9660) {
5001c2e5b02Smartin sess = label.d_partitions[part].p_cdsession;
5011c2e5b02Smartin sprintf(dname, "/dev/r%s%c", device, 'a'+part);
50250dbef1aSdholland dev = open(dname, O_RDONLY, 0);
50350dbef1aSdholland if (dev == -1)
50450dbef1aSdholland continue;
505ea2cbdfdSmrg error = get_iso9660_volname(dev, sess, volname,
506ea2cbdfdSmrg sizeof volname);
50750dbef1aSdholland close(dev);
5081c2e5b02Smartin if (error)
5091c2e5b02Smartin continue;
5101c2e5b02Smartin sprintf(state->info->device_name,
5111c2e5b02Smartin "%s%c", device, 'a'+part);
5121c2e5b02Smartin sprintf(state->info->menu, "%s (%s)",
5131c2e5b02Smartin state->info->device_name, volname);
51450dbef1aSdholland } else {
51550dbef1aSdholland /*
51650dbef1aSdholland * All install CDs use partition
51750dbef1aSdholland * a for the sets.
51850dbef1aSdholland */
51950dbef1aSdholland if (part > 0)
52050dbef1aSdholland continue;
5211c2e5b02Smartin sprintf(state->info->device_name,
5221c2e5b02Smartin "%s%c", device, 'a'+part);
5231c2e5b02Smartin strcpy(state->info->menu, state->info->device_name);
52450dbef1aSdholland }
5251c2e5b02Smartin state->info++;
5261c2e5b02Smartin if (++state->count >= MAX_CD_INFOS)
5271c2e5b02Smartin return false;
52850dbef1aSdholland }
5291c2e5b02Smartin
5301c2e5b02Smartin return true;
53150dbef1aSdholland }
5321c2e5b02Smartin
5331c2e5b02Smartin /*
5341c2e5b02Smartin * Get a list of all available CD media (not drives!), return
5351c2e5b02Smartin * the number of entries collected.
5361c2e5b02Smartin */
5371c2e5b02Smartin static int
get_available_cds(void)5381c2e5b02Smartin get_available_cds(void)
5391c2e5b02Smartin {
5401c2e5b02Smartin struct get_available_cds_state data;
541a4668228Smartin int n, m;
5421c2e5b02Smartin
54304645caaSmartin memset(&data, 0, sizeof data);
5441c2e5b02Smartin data.info = cds;
54504645caaSmartin
54604645caaSmartin n = getvfsstat(NULL, 0, ST_NOWAIT);
54704645caaSmartin if (n > 0) {
54804645caaSmartin data.mounted = calloc(n, sizeof(*data.mounted));
549a4668228Smartin m = getvfsstat(data.mounted, n*sizeof(*data.mounted),
55004645caaSmartin ST_NOWAIT);
551a4668228Smartin assert(m >= 0 && m <= n);
552a4668228Smartin data.num_mounted = m;
55304645caaSmartin }
5541c2e5b02Smartin
5551c2e5b02Smartin enumerate_disks(&data, get_available_cds_helper);
5561c2e5b02Smartin
55704645caaSmartin free(data.mounted);
55804645caaSmartin
5591c2e5b02Smartin return data.count;
56050dbef1aSdholland }
56150dbef1aSdholland
56250dbef1aSdholland static int
cd_has_sets(void)56350dbef1aSdholland cd_has_sets(void)
56450dbef1aSdholland {
565da165701Smartin
566da165701Smartin /* sanity check */
567da165701Smartin if (cdrom_dev[0] == 0)
568da165701Smartin return 0;
569da165701Smartin
57050dbef1aSdholland /* Mount it */
57150dbef1aSdholland if (run_program(RUN_SILENT, "/sbin/mount -rt cd9660 /dev/%s /mnt2",
57250dbef1aSdholland cdrom_dev) != 0)
57350dbef1aSdholland return 0;
57450dbef1aSdholland
57550dbef1aSdholland mnt2_mounted = 1;
57650dbef1aSdholland
57750dbef1aSdholland snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s", "/mnt2", set_dir_bin);
57850dbef1aSdholland snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s", "/mnt2", set_dir_src);
57950dbef1aSdholland return dir_exists_p(ext_dir_bin);
58050dbef1aSdholland }
58150dbef1aSdholland
58250dbef1aSdholland /*
58350dbef1aSdholland * Check whether we can remove the boot media.
58450dbef1aSdholland * If it is not a local filesystem, return -1.
58550dbef1aSdholland * If we can not decide for sure (can not tell MD content from plain ffs
58650dbef1aSdholland * on hard disk, for example), return 0.
58750dbef1aSdholland * If it is a CD/DVD, return 1.
58850dbef1aSdholland */
58950dbef1aSdholland int
boot_media_still_needed(void)59050dbef1aSdholland boot_media_still_needed(void)
59150dbef1aSdholland {
59250dbef1aSdholland struct statvfs sb;
59350dbef1aSdholland
59450dbef1aSdholland if (statvfs("/", &sb) == 0) {
59550dbef1aSdholland if (!(sb.f_flag & ST_LOCAL))
59650dbef1aSdholland return -1;
59750dbef1aSdholland if (strcmp(sb.f_fstypename, MOUNT_CD9660) == 0
59850dbef1aSdholland || strcmp(sb.f_fstypename, MOUNT_UDF) == 0)
59950dbef1aSdholland return 1;
60050dbef1aSdholland }
60150dbef1aSdholland
60250dbef1aSdholland return 0;
60350dbef1aSdholland }
60450dbef1aSdholland
60532ccf04cSmartin bool
root_is_read_only(void)60632ccf04cSmartin root_is_read_only(void)
60732ccf04cSmartin {
60832ccf04cSmartin struct statvfs sb;
60932ccf04cSmartin
61032ccf04cSmartin if (statvfs("/", &sb) == 0)
61132ccf04cSmartin return sb.f_flag & ST_RDONLY;
61232ccf04cSmartin
61332ccf04cSmartin return false;
61432ccf04cSmartin }
61532ccf04cSmartin
61650dbef1aSdholland /*
61750dbef1aSdholland * Get from a CDROM distribution.
61850dbef1aSdholland * Also used on "installation using bootable install media"
61950dbef1aSdholland * as the default option in the "distmedium" menu.
62050dbef1aSdholland */
62150dbef1aSdholland int
get_via_cdrom(void)62250dbef1aSdholland get_via_cdrom(void)
62350dbef1aSdholland {
62450dbef1aSdholland menu_ent cd_menu[MAX_CD_INFOS];
62550dbef1aSdholland struct stat sb;
626e21052b4Smartin int rv, num_cds, menu_cd, i, selected_cd = 0;
62750dbef1aSdholland int mib[2];
62850dbef1aSdholland char rootdev[SSTRSIZE] = "";
62950dbef1aSdholland size_t varlen;
63050dbef1aSdholland
63150dbef1aSdholland /* If root is not md(4) and we have set dir, skip this step. */
63250dbef1aSdholland mib[0] = CTL_KERN;
63350dbef1aSdholland mib[1] = KERN_ROOT_DEVICE;
63450dbef1aSdholland varlen = sizeof(rootdev);
63550dbef1aSdholland (void)sysctl(mib, 2, rootdev, &varlen, NULL, 0);
63650dbef1aSdholland if (stat(set_dir_bin, &sb) == 0 && S_ISDIR(sb.st_mode) &&
63750dbef1aSdholland strncmp("md", rootdev, 2) != 0) {
63850dbef1aSdholland strlcpy(ext_dir_bin, set_dir_bin, sizeof ext_dir_bin);
63950dbef1aSdholland strlcpy(ext_dir_src, set_dir_src, sizeof ext_dir_src);
64050dbef1aSdholland return SET_OK;
64150dbef1aSdholland }
64250dbef1aSdholland
643ce713491Schristos memset(cd_menu, 0, sizeof(cd_menu));
64450dbef1aSdholland num_cds = get_available_cds();
64550dbef1aSdholland if (num_cds <= 0) {
646da165701Smartin msg_display(MSG_No_cd_found);
647da165701Smartin cdrom_dev[0] = 0;
64850dbef1aSdholland } else if (num_cds == 1) {
64950dbef1aSdholland /* single CD found, check for sets on it */
65050dbef1aSdholland strcpy(cdrom_dev, cds[0].device_name);
65150dbef1aSdholland if (cd_has_sets())
65250dbef1aSdholland return SET_OK;
65350dbef1aSdholland } else {
65450dbef1aSdholland for (i = 0; i< num_cds; i++) {
65550dbef1aSdholland cd_menu[i].opt_name = cds[i].menu;
65650dbef1aSdholland cd_menu[i].opt_flags = OPT_EXIT;
6574b2364d9Smartin cd_menu[i].opt_action = set_menu_select;
65850dbef1aSdholland }
65950dbef1aSdholland /* create a menu offering available choices */
66050dbef1aSdholland menu_cd = new_menu(MSG_Available_cds,
66150dbef1aSdholland cd_menu, num_cds, -1, 4, 0, 0,
66250dbef1aSdholland MC_SCROLL | MC_NOEXITOPT,
66350dbef1aSdholland NULL, NULL, NULL, NULL, NULL);
66450dbef1aSdholland if (menu_cd == -1)
66550dbef1aSdholland return SET_RETRY;
66650dbef1aSdholland msg_display(MSG_ask_cd);
66750dbef1aSdholland process_menu(menu_cd, &selected_cd);
66850dbef1aSdholland free_menu(menu_cd);
66950dbef1aSdholland strcpy(cdrom_dev, cds[selected_cd].device_name);
67050dbef1aSdholland if (cd_has_sets())
67150dbef1aSdholland return SET_OK;
67250dbef1aSdholland }
67350dbef1aSdholland
674da165701Smartin if (num_cds >= 1 && mnt2_mounted) {
67550dbef1aSdholland umount_mnt2();
6764103857bSmartin hit_enter_to_continue(MSG_cd_path_not_found, NULL);
67750dbef1aSdholland }
67850dbef1aSdholland
67950dbef1aSdholland /* ask for paths on the CD */
680e21052b4Smartin rv = -1;
681e21052b4Smartin process_menu(MENU_cdromsource, &rv);
682da165701Smartin if (rv == SET_RETRY || rv == SET_ABANDON)
683da165701Smartin return rv;
68450dbef1aSdholland
68550dbef1aSdholland if (cd_has_sets())
68650dbef1aSdholland return SET_OK;
68750dbef1aSdholland
68850dbef1aSdholland return SET_RETRY;
68950dbef1aSdholland }
69050dbef1aSdholland
69150dbef1aSdholland
69250dbef1aSdholland /*
69350dbef1aSdholland * Get from a pathname inside an unmounted local filesystem
69450dbef1aSdholland * (e.g., where sets were preloaded onto a local DOS partition)
69550dbef1aSdholland */
69650dbef1aSdholland int
get_via_localfs(void)69750dbef1aSdholland get_via_localfs(void)
69850dbef1aSdholland {
699e21052b4Smartin int rv = -1;
700e21052b4Smartin
70150dbef1aSdholland /* Get device, filesystem, and filepath */
702e21052b4Smartin process_menu (MENU_localfssource, &rv);
703e21052b4Smartin if (rv == SET_RETRY)
7044b2364d9Smartin return SET_RETRY;
70550dbef1aSdholland
70650dbef1aSdholland /* Mount it */
70750dbef1aSdholland if (run_program(0, "/sbin/mount -rt %s /dev/%s /mnt2",
70850dbef1aSdholland localfs_fs, localfs_dev))
70950dbef1aSdholland return SET_RETRY;
71050dbef1aSdholland
71150dbef1aSdholland mnt2_mounted = 1;
71250dbef1aSdholland
71350dbef1aSdholland snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s/%s",
71450dbef1aSdholland "/mnt2", localfs_dir, set_dir_bin);
71550dbef1aSdholland snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s/%s",
71650dbef1aSdholland "/mnt2", localfs_dir, set_dir_src);
71750dbef1aSdholland
71850dbef1aSdholland return SET_OK;
71950dbef1aSdholland }
72050dbef1aSdholland
72150dbef1aSdholland /*
72250dbef1aSdholland * Get from an already-mounted pathname.
72350dbef1aSdholland */
72450dbef1aSdholland
72550dbef1aSdholland int
get_via_localdir(void)72650dbef1aSdholland get_via_localdir(void)
72750dbef1aSdholland {
728e21052b4Smartin int rv = -1;
729e21052b4Smartin
73050dbef1aSdholland /* Get filepath */
731e21052b4Smartin process_menu(MENU_localdirsource, &rv);
732e21052b4Smartin if (rv == SET_RETRY)
7334b2364d9Smartin return SET_RETRY;
73450dbef1aSdholland
73550dbef1aSdholland /*
73650dbef1aSdholland * We have to have an absolute path ('cos pax runs in a
73750dbef1aSdholland * different directory), make it so.
73850dbef1aSdholland */
73950dbef1aSdholland snprintf(ext_dir_bin, sizeof ext_dir_bin, "/%s/%s", localfs_dir, set_dir_bin);
74050dbef1aSdholland snprintf(ext_dir_src, sizeof ext_dir_src, "/%s/%s", localfs_dir, set_dir_src);
74150dbef1aSdholland
74250dbef1aSdholland return SET_OK;
74350dbef1aSdholland }
74450dbef1aSdholland
74550dbef1aSdholland
74650dbef1aSdholland /*
74750dbef1aSdholland * Support for custom distribution fetches / unpacks.
74850dbef1aSdholland */
74950dbef1aSdholland
75050dbef1aSdholland unsigned int
set_X11_selected(void)75150dbef1aSdholland set_X11_selected(void)
75250dbef1aSdholland {
75350dbef1aSdholland int i;
75450dbef1aSdholland
75550dbef1aSdholland for (i = SET_X11_FIRST; ++i < SET_X11_LAST;)
75650dbef1aSdholland if (set_status[i] & SET_SELECTED)
75750dbef1aSdholland return 1;
75850dbef1aSdholland return 0;
75950dbef1aSdholland }
76050dbef1aSdholland
76150dbef1aSdholland unsigned int
get_kernel_set(void)76250dbef1aSdholland get_kernel_set(void)
76350dbef1aSdholland {
76450dbef1aSdholland int i;
76550dbef1aSdholland
76650dbef1aSdholland for (i = SET_KERNEL_FIRST; ++i < SET_KERNEL_LAST;)
76750dbef1aSdholland if (set_status[i] & SET_SELECTED)
76850dbef1aSdholland return i;
76950dbef1aSdholland return SET_NONE;
77050dbef1aSdholland }
77150dbef1aSdholland
77250dbef1aSdholland void
set_kernel_set(unsigned int kernel_set)77350dbef1aSdholland set_kernel_set(unsigned int kernel_set)
77450dbef1aSdholland {
77550dbef1aSdholland int i;
77650dbef1aSdholland
77750dbef1aSdholland /* only one kernel set is allowed */
77850dbef1aSdholland for (i = SET_KERNEL_FIRST; ++i < SET_KERNEL_LAST;)
77950dbef1aSdholland set_status[i] &= ~SET_SELECTED;
78050dbef1aSdholland set_status[kernel_set] |= SET_SELECTED;
78150dbef1aSdholland }
78250dbef1aSdholland
783249ed7a6Smartin void
set_noextract_set(unsigned int set)784249ed7a6Smartin set_noextract_set(unsigned int set)
785249ed7a6Smartin {
786249ed7a6Smartin
787249ed7a6Smartin set_status[set] |= SET_NO_EXTRACT;
788249ed7a6Smartin }
789249ed7a6Smartin
79050dbef1aSdholland static int
set_toggle(menudesc * menu,void * arg)79150dbef1aSdholland set_toggle(menudesc *menu, void *arg)
79250dbef1aSdholland {
79350dbef1aSdholland distinfo **distp = arg;
79450dbef1aSdholland int set = distp[menu->cursel]->set;
79550dbef1aSdholland
79650dbef1aSdholland if (set > SET_KERNEL_FIRST && set < SET_KERNEL_LAST &&
79750dbef1aSdholland !(set_status[set] & SET_SELECTED))
79850dbef1aSdholland set_kernel_set(set);
79950dbef1aSdholland else
80050dbef1aSdholland set_status[set] ^= SET_SELECTED;
80150dbef1aSdholland return 0;
80250dbef1aSdholland }
80350dbef1aSdholland
80450dbef1aSdholland static int
set_all_none(menudesc * menu,void * arg,int set,int clr)80550dbef1aSdholland set_all_none(menudesc *menu, void *arg, int set, int clr)
80650dbef1aSdholland {
80750dbef1aSdholland distinfo **distp = arg;
80850dbef1aSdholland distinfo *dist = *distp;
80950dbef1aSdholland int nested;
81050dbef1aSdholland
81150dbef1aSdholland for (nested = 0; dist->set != SET_GROUP_END || nested--; dist++) {
81250dbef1aSdholland if (dist->set == SET_GROUP) {
81350dbef1aSdholland nested++;
81450dbef1aSdholland continue;
81550dbef1aSdholland }
81650dbef1aSdholland set_status[dist->set] = (set_status[dist->set] & ~clr) | set;
81750dbef1aSdholland }
81850dbef1aSdholland return 0;
81950dbef1aSdholland }
82050dbef1aSdholland
82150dbef1aSdholland static int
set_all(menudesc * menu,void * arg)82250dbef1aSdholland set_all(menudesc *menu, void *arg)
82350dbef1aSdholland {
82450dbef1aSdholland return set_all_none(menu, arg, SET_SELECTED, 0);
82550dbef1aSdholland }
82650dbef1aSdholland
82750dbef1aSdholland static int
set_none(menudesc * menu,void * arg)82850dbef1aSdholland set_none(menudesc *menu, void *arg)
82950dbef1aSdholland {
83050dbef1aSdholland return set_all_none(menu, arg, 0, SET_SELECTED);
83150dbef1aSdholland }
83250dbef1aSdholland
83350dbef1aSdholland static void
set_label(menudesc * menu,int opt,void * arg)83450dbef1aSdholland set_label(menudesc *menu, int opt, void *arg)
83550dbef1aSdholland {
83650dbef1aSdholland distinfo **distp = arg;
83750dbef1aSdholland distinfo *dist = distp[opt];
83850dbef1aSdholland const char *selected;
83950dbef1aSdholland const char *desc;
84050dbef1aSdholland int nested;
84150dbef1aSdholland
84250dbef1aSdholland desc = dist->desc;
84350dbef1aSdholland
84450dbef1aSdholland if (dist->set != SET_GROUP)
84550dbef1aSdholland selected = set_status[dist->set] & SET_SELECTED ? msg_yes : msg_no;
84650dbef1aSdholland else {
84750dbef1aSdholland /* sub menu - display None/Some/All */
84850dbef1aSdholland nested = 0;
84950dbef1aSdholland selected = "unknown";
85050dbef1aSdholland while ((++dist)->set != SET_GROUP_END || nested--) {
85150dbef1aSdholland if (dist->set == SET_GROUP) {
85250dbef1aSdholland nested++;
85350dbef1aSdholland continue;
85450dbef1aSdholland }
85550dbef1aSdholland if (!(set_status[dist->set] & SET_VALID))
85650dbef1aSdholland continue;
85750dbef1aSdholland if (set_status[dist->set] & SET_SELECTED) {
85850dbef1aSdholland if (selected == msg_none) {
85950dbef1aSdholland selected = msg_some;
86050dbef1aSdholland break;
86150dbef1aSdholland }
86250dbef1aSdholland selected = msg_all;
86350dbef1aSdholland } else {
86450dbef1aSdholland if (selected == msg_all) {
86550dbef1aSdholland selected = msg_some;
86650dbef1aSdholland break;
86750dbef1aSdholland }
86850dbef1aSdholland selected = msg_none;
86950dbef1aSdholland }
87050dbef1aSdholland }
87150dbef1aSdholland }
87250dbef1aSdholland
873*050294faShannken wprintw(menu->mw, "%-40s %s", msg_string(desc), selected);
87450dbef1aSdholland }
87550dbef1aSdholland
87650dbef1aSdholland static int set_sublist(menudesc *menu, void *arg);
87750dbef1aSdholland
87850dbef1aSdholland static int
initialise_set_menu(distinfo * dist,menu_ent * me,distinfo ** de,int all_none)87950dbef1aSdholland initialise_set_menu(distinfo *dist, menu_ent *me, distinfo **de, int all_none)
88050dbef1aSdholland {
88150dbef1aSdholland int set;
88250dbef1aSdholland int sets;
88350dbef1aSdholland int nested;
88450dbef1aSdholland
88550dbef1aSdholland for (sets = 0; ; dist++) {
88650dbef1aSdholland set = dist->set;
88750dbef1aSdholland if (set == SET_LAST || set == SET_GROUP_END)
88850dbef1aSdholland break;
88950dbef1aSdholland if (!(set_status[set] & SET_VALID))
89050dbef1aSdholland continue;
89150dbef1aSdholland *de = dist;
892ce713491Schristos memset(me, 0, sizeof(*me));
89350dbef1aSdholland if (set != SET_GROUP)
89450dbef1aSdholland me->opt_action = set_toggle;
89550dbef1aSdholland else {
89650dbef1aSdholland /* Collapse sublist */
89750dbef1aSdholland nested = 0;
89850dbef1aSdholland while ((++dist)->set != SET_GROUP_END || nested--) {
89950dbef1aSdholland if (dist->set == SET_GROUP)
90050dbef1aSdholland nested++;
90150dbef1aSdholland }
90250dbef1aSdholland me->opt_action = set_sublist;
90350dbef1aSdholland }
90450dbef1aSdholland sets++;
90550dbef1aSdholland de++;
90650dbef1aSdholland me++;
90750dbef1aSdholland }
90850dbef1aSdholland
90950dbef1aSdholland if (all_none) {
91050dbef1aSdholland me->opt_name = MSG_select_all;
91150dbef1aSdholland me->opt_action = set_all;
91250dbef1aSdholland me++;
91350dbef1aSdholland me->opt_name = MSG_select_none;
91450dbef1aSdholland me->opt_action = set_none;
91550dbef1aSdholland sets += 2;
91650dbef1aSdholland }
91750dbef1aSdholland
91850dbef1aSdholland return sets;
91950dbef1aSdholland }
92050dbef1aSdholland
92150dbef1aSdholland static int
set_sublist(menudesc * menu,void * arg)92250dbef1aSdholland set_sublist(menudesc *menu, void *arg)
92350dbef1aSdholland {
92450dbef1aSdholland distinfo *de[SET_LAST];
92550dbef1aSdholland menu_ent me[SET_LAST];
92650dbef1aSdholland distinfo **dist = arg;
92750dbef1aSdholland int menu_no;
92850dbef1aSdholland int sets;
92950dbef1aSdholland
930ce713491Schristos memset(me, 0, sizeof(me));
93150dbef1aSdholland sets = initialise_set_menu(dist[menu->cursel] + 1, me, de, 1);
93250dbef1aSdholland
93350dbef1aSdholland menu_no = new_menu(NULL, me, sets, 20, 10, 0, select_menu_width,
93450dbef1aSdholland MC_SUBMENU | MC_SCROLL | MC_DFLTEXIT,
93550dbef1aSdholland NULL, set_label, NULL, NULL,
93650dbef1aSdholland MSG_install_selected_sets);
93750dbef1aSdholland
93850dbef1aSdholland process_menu(menu_no, de);
93950dbef1aSdholland free_menu(menu_no);
94050dbef1aSdholland
94150dbef1aSdholland return 0;
94250dbef1aSdholland }
94350dbef1aSdholland
94450dbef1aSdholland void
customise_sets(void)94550dbef1aSdholland customise_sets(void)
94650dbef1aSdholland {
94750dbef1aSdholland distinfo *de[SET_LAST];
94850dbef1aSdholland menu_ent me[SET_LAST];
94950dbef1aSdholland int sets;
95050dbef1aSdholland int menu_no;
95150dbef1aSdholland
95250dbef1aSdholland msg_display(MSG_cur_distsets);
95350dbef1aSdholland msg_table_add(MSG_cur_distsets_header);
95450dbef1aSdholland
955ce713491Schristos memset(me, 0, sizeof(me));
95650dbef1aSdholland sets = initialise_set_menu(dist_list, me, de, 0);
95750dbef1aSdholland
95850dbef1aSdholland menu_no = new_menu(NULL, me, sets, 0, 5, 0, select_menu_width,
95950dbef1aSdholland MC_SCROLL | MC_NOBOX | MC_DFLTEXIT | MC_NOCLEAR,
96050dbef1aSdholland NULL, set_label, NULL, NULL,
96150dbef1aSdholland MSG_install_selected_sets);
96250dbef1aSdholland
96350dbef1aSdholland process_menu(menu_no, de);
96450dbef1aSdholland free_menu(menu_no);
96550dbef1aSdholland }
96650dbef1aSdholland
96750dbef1aSdholland /*
96850dbef1aSdholland * Extract_file **REQUIRES** an absolute path in ext_dir. Any code
96950dbef1aSdholland * that sets up xfer_dir for use by extract_file needs to put in the
97050dbef1aSdholland * full path name to the directory.
97150dbef1aSdholland */
97250dbef1aSdholland
97350dbef1aSdholland int
extract_file(distinfo * dist,int update)97450dbef1aSdholland extract_file(distinfo *dist, int update)
97550dbef1aSdholland {
976249ed7a6Smartin const char *dest_dir = NULL;
977249ed7a6Smartin
978249ed7a6Smartin if (update && (dist->set == SET_ETC || dist->set == SET_X11_ETC)) {
979249ed7a6Smartin dest_dir = "/.sysinst";
980249ed7a6Smartin make_target_dir(dest_dir);
981249ed7a6Smartin } else if (dist->set == SET_PKGSRC)
982249ed7a6Smartin dest_dir = "/usr";
983249ed7a6Smartin else
984249ed7a6Smartin dest_dir = "/";
985249ed7a6Smartin
986249ed7a6Smartin return extract_file_to(dist, update, dest_dir, NULL, true);
987249ed7a6Smartin }
988249ed7a6Smartin
989249ed7a6Smartin int
extract_file_to(distinfo * dist,int update,const char * dest_dir,const char * extr_pattern,bool do_stats)990249ed7a6Smartin extract_file_to(distinfo *dist, int update, const char *dest_dir,
991249ed7a6Smartin const char *extr_pattern, bool do_stats)
992249ed7a6Smartin {
99350dbef1aSdholland char path[STRSIZE];
99450dbef1aSdholland char *owd;
99550dbef1aSdholland int rval;
99650dbef1aSdholland
99750dbef1aSdholland /* If we might need to tidy up, ensure directory exists */
99850dbef1aSdholland if (fetch_fn != NULL)
99950dbef1aSdholland make_target_dir(xfer_dir);
100050dbef1aSdholland
100150dbef1aSdholland (void)snprintf(path, sizeof path, "%s/%s%s",
10020ef20e92Smartin ext_dir_for_set(dist->name), dist->name, set_postfix(dist->name));
100350dbef1aSdholland
100450dbef1aSdholland owd = getcwd(NULL, 0);
100550dbef1aSdholland
100650dbef1aSdholland /* Do we need to fetch the file now? */
100750dbef1aSdholland if (fetch_fn != NULL) {
100850dbef1aSdholland rval = fetch_fn(dist->name);
100950dbef1aSdholland if (rval != SET_OK)
101050dbef1aSdholland return rval;
101150dbef1aSdholland }
101250dbef1aSdholland
101350dbef1aSdholland /* check tarfile exists */
101450dbef1aSdholland if (!file_exists_p(path)) {
101550dbef1aSdholland
101650dbef1aSdholland #ifdef SUPPORT_8_3_SOURCE_FILESYSTEM
101750dbef1aSdholland /*
101850dbef1aSdholland * Update path to use dist->name truncated to the first eight
101950dbef1aSdholland * characters and check again
102050dbef1aSdholland */
10211b565566Smartin (void)snprintf(path, sizeof path,
10221b565566Smartin "%s/%.8s%.4s", /* 4 as includes '.' */
10231b565566Smartin ext_dir_for_set(dist->name), dist->name,
10241b565566Smartin set_postfix(dist->name));
10251b565566Smartin
102650dbef1aSdholland if (!file_exists_p(path)) {
102750dbef1aSdholland #endif /* SUPPORT_8_3_SOURCE_FILESYSTEM */
1028249ed7a6Smartin if (do_stats)
102950dbef1aSdholland tarstats.nnotfound++;
103050dbef1aSdholland
10311b565566Smartin char *err = str_arg_subst(msg_string(MSG_notarfile),
10321b565566Smartin 1, &dist->name);
10331b565566Smartin hit_enter_to_continue(err, NULL);
10341b565566Smartin free(err);
103531a289cdSmartin free(owd);
103650dbef1aSdholland return SET_RETRY;
103750dbef1aSdholland }
103850dbef1aSdholland #ifdef SUPPORT_8_3_SOURCE_FILESYSTEM
103950dbef1aSdholland }
104050dbef1aSdholland #endif /* SUPPORT_8_3_SOURCE_FILESYSTEM */
104150dbef1aSdholland
1042249ed7a6Smartin if (do_stats)
104350dbef1aSdholland tarstats.nfound++;
104450dbef1aSdholland /* cd to the target root. */
1045249ed7a6Smartin target_chdir_or_die(dest_dir);
104650dbef1aSdholland
104750dbef1aSdholland /*
104850dbef1aSdholland * /usr/X11R7/lib/X11/xkb/symbols/pc was a directory in 5.0
104950dbef1aSdholland * but is a file in 5.1 and beyond, so on upgrades we need to
105050dbef1aSdholland * delete it before extracting the xbase set.
105150dbef1aSdholland */
105250dbef1aSdholland if (update && dist->set == SET_X11_BASE)
105350dbef1aSdholland run_program(0, "rm -rf usr/X11R7/lib/X11/xkb/symbols/pc");
105450dbef1aSdholland
105550dbef1aSdholland /* now extract set files into "./". */
1056249ed7a6Smartin if (extr_pattern != NULL) {
1057249ed7a6Smartin rval = run_program(RUN_DISPLAY | RUN_PROGRESS,
1058249ed7a6Smartin "progress -zf %s tar --chroot "
1059249ed7a6Smartin TAR_EXTRACT_FLAGS " - '%s'",
1060249ed7a6Smartin path, extr_pattern);
1061249ed7a6Smartin } else {
106250dbef1aSdholland rval = run_program(RUN_DISPLAY | RUN_PROGRESS,
1063b76c9f8fSmartin "progress -zf %s tar --chroot "
1064b76c9f8fSmartin TAR_EXTRACT_FLAGS " -", path);
1065249ed7a6Smartin }
106650dbef1aSdholland
106750dbef1aSdholland chdir(owd);
106850dbef1aSdholland free(owd);
106950dbef1aSdholland
107050dbef1aSdholland /* Check rval for errors and give warning. */
107150dbef1aSdholland if (rval != 0) {
1072249ed7a6Smartin if (do_stats)
107350dbef1aSdholland tarstats.nerror++;
107424ecf24eSchristos msg_fmt_display(MSG_tarerror, "%s", path);
10754103857bSmartin hit_enter_to_continue(NULL, NULL);
107650dbef1aSdholland return SET_RETRY;
107750dbef1aSdholland }
107850dbef1aSdholland
107950dbef1aSdholland if (fetch_fn != NULL && clean_xfer_dir) {
108050dbef1aSdholland run_program(0, "rm %s", path);
108150dbef1aSdholland /* Plausibly we should unlink an empty xfer_dir as well */
108250dbef1aSdholland }
108350dbef1aSdholland
108450dbef1aSdholland set_status[dist->set] |= SET_INSTALLED;
1085249ed7a6Smartin if (do_stats)
108650dbef1aSdholland tarstats.nsuccess++;
108750dbef1aSdholland return SET_OK;
108850dbef1aSdholland }
108950dbef1aSdholland
109050dbef1aSdholland static void
skip_set(distinfo * dist,int skip_type)109150dbef1aSdholland skip_set(distinfo *dist, int skip_type)
109250dbef1aSdholland {
109350dbef1aSdholland int nested;
109450dbef1aSdholland int set;
109550dbef1aSdholland
109650dbef1aSdholland nested = 0;
109750dbef1aSdholland while ((++dist)->set != SET_GROUP_END || nested--) {
109850dbef1aSdholland set = dist->set;
109950dbef1aSdholland if (set == SET_GROUP) {
110050dbef1aSdholland nested++;
110150dbef1aSdholland continue;
110250dbef1aSdholland }
110350dbef1aSdholland if (set == SET_LAST)
110450dbef1aSdholland break;
110550dbef1aSdholland if (set_status[set] == (SET_SELECTED | SET_VALID))
110650dbef1aSdholland set_status[set] |= SET_SKIPPED;
110750dbef1aSdholland tarstats.nskipped++;
110850dbef1aSdholland }
110950dbef1aSdholland }
111050dbef1aSdholland
1111249ed7a6Smartin distinfo*
get_set_distinfo(int opt)1112249ed7a6Smartin get_set_distinfo(int opt)
1113249ed7a6Smartin {
1114249ed7a6Smartin distinfo *dist;
1115249ed7a6Smartin int set;
1116249ed7a6Smartin
1117249ed7a6Smartin for (dist = dist_list; (set = dist->set) != SET_LAST; dist++) {
1118249ed7a6Smartin if (set != opt)
1119249ed7a6Smartin continue;
1120249ed7a6Smartin if (dist->name == NULL)
1121249ed7a6Smartin continue;
1122249ed7a6Smartin if ((set_status[set] & (SET_VALID | SET_SELECTED))
1123249ed7a6Smartin != (SET_VALID | SET_SELECTED))
1124249ed7a6Smartin continue;
1125249ed7a6Smartin return dist;
1126249ed7a6Smartin }
1127249ed7a6Smartin
1128249ed7a6Smartin return NULL;
1129249ed7a6Smartin }
1130249ed7a6Smartin
1131043e812bSmartin #ifdef CHECK_ENTROPY
1132043e812bSmartin
1133043e812bSmartin char entropy_file[PATH_MAX];
1134043e812bSmartin
1135043e812bSmartin /*
1136043e812bSmartin * Are we short of entropy?
1137043e812bSmartin */
113803af0822Smartin size_t
entropy_needed(void)1139043e812bSmartin entropy_needed(void)
1140043e812bSmartin {
1141043e812bSmartin int needed;
1142043e812bSmartin size_t len;
1143043e812bSmartin
1144043e812bSmartin len = sizeof(needed);
1145043e812bSmartin if (sysctlbyname("kern.entropy.needed", &needed, &len, NULL, 0))
1146043e812bSmartin return 0;
1147043e812bSmartin
1148043e812bSmartin if (needed < 0)
1149043e812bSmartin return 0;
1150043e812bSmartin
1151043e812bSmartin return needed;
1152043e812bSmartin }
1153043e812bSmartin
1154043e812bSmartin static void
entropy_write_to_kernel(const uint8_t * data,size_t len)1155043e812bSmartin entropy_write_to_kernel(const uint8_t *data, size_t len)
1156043e812bSmartin {
1157043e812bSmartin int fd;
1158043e812bSmartin
1159043e812bSmartin fd = open(_PATH_RANDOM, O_RDWR, 0);
1160043e812bSmartin if (fd >= 0) {
1161043e812bSmartin write(fd, data, len);
1162043e812bSmartin close(fd);
1163043e812bSmartin }
1164043e812bSmartin }
1165043e812bSmartin
1166043e812bSmartin static void
entropy_add_manual(void)1167043e812bSmartin entropy_add_manual(void)
1168043e812bSmartin {
1169043e812bSmartin SHA256_CTX ctx;
117003af0822Smartin char buf[256];
1171043e812bSmartin uint8_t digest[SHA256_DIGEST_LENGTH];
11721e0c64adSmartin static const char prompt[] = "> ";
117303af0822Smartin size_t l;
117418183f70Smartin int txt_y;
1175043e812bSmartin
1176043e812bSmartin msg_display(MSG_entropy_enter_manual1);
1177043e812bSmartin msg_printf("\n\n");
1178043e812bSmartin msg_display_add(MSG_entropy_enter_manual2);
117918183f70Smartin msg_printf("\n\n dd if=/dev/random bs=32 count=1 | openssl base64\n\n");
1180043e812bSmartin msg_display_add(MSG_entropy_enter_manual3);
1181043e812bSmartin msg_printf("\n\n");
1182043e812bSmartin SHA256_Init(&ctx);
118318183f70Smartin txt_y = getcury(mainwin)+1;
118403af0822Smartin
118503af0822Smartin echo();
118603af0822Smartin wmove(mainwin, txt_y, 0);
11871e0c64adSmartin msg_fmt_table_add(prompt, prompt);
118803af0822Smartin mvwgetnstr(mainwin, txt_y, 2, buf, sizeof buf);
1189043e812bSmartin l = strlen(buf);
1190043e812bSmartin if (l > 0)
1191043e812bSmartin SHA256_Update(&ctx, (const uint8_t*)buf, l);
119203af0822Smartin noecho();
1193043e812bSmartin SHA256_Final(digest, &ctx);
1194043e812bSmartin
119518183f70Smartin wmove(mainwin, txt_y-1, 0);
119603af0822Smartin wclrtobot(mainwin);
119703af0822Smartin wrefresh(mainwin);
119803af0822Smartin
1199043e812bSmartin entropy_write_to_kernel(digest, sizeof digest);
1200043e812bSmartin }
1201043e812bSmartin
1202043e812bSmartin /*
1203d56a0f03Sgson * Get a file by some means and return a (potentially only
1204043e812bSmartin * temporary valid) path to the local copy.
1205043e812bSmartin * If mountpt is nonempty, the caller should unmount that
1206043e812bSmartin * directory after processing the file.
1207043e812bSmartin * Return success if the file is available, or failure if
1208d56a0f03Sgson * the user cancelled the request or network transfer failed.
1209043e812bSmartin */
1210043e812bSmartin static bool
entropy_get_file(bool use_netbsd_seed,char * path)1211043e812bSmartin entropy_get_file(bool use_netbsd_seed, char *path)
1212043e812bSmartin {
1213043e812bSmartin static struct ftpinfo server = { .user = "ftp" };
121478ab2ae0Smartin char url[STRSIZE], tmpf[PATH_MAX], mountpt[PATH_MAX];
1215043e812bSmartin const char *ftp_opt;
1216043e812bSmartin arg_rv arg;
1217043e812bSmartin int rv = 0;
1218043e812bSmartin const char *file_desc = msg_string(use_netbsd_seed ?
1219043e812bSmartin MSG_entropy_seed : MSG_entropy_data);
1220043e812bSmartin char *dir;
1221043e812bSmartin
1222043e812bSmartin path[0] = 0;
1223043e812bSmartin mountpt[0] = 0;
1224043e812bSmartin
122578ab2ae0Smartin sprintf(tmpf, "/tmp/entr.%06x", getpid());
1226043e812bSmartin
1227043e812bSmartin msg_display(use_netbsd_seed ?
1228043e812bSmartin MSG_entropy_seed_hdr : MSG_entropy_data_hdr);
1229043e812bSmartin msg_printf("\n\n %s\n\n",
1230043e812bSmartin use_netbsd_seed ?
1231043e812bSmartin "rndctl -S /tmp/entropy-file" :
1232043e812bSmartin "dd if=/dev/random bs=32 count=1 of=/tmp/random.tmp");
1233043e812bSmartin strcpy(entropy_file, use_netbsd_seed ?
1234043e812bSmartin "entropy-file" : "random.tmp");
1235043e812bSmartin process_menu(MENU_entropy_select_file, &rv);
1236043e812bSmartin switch (rv) {
1237043e812bSmartin case 1:
1238043e812bSmartin case 2:
1239043e812bSmartin #ifndef DEBUG
1240043e812bSmartin if (!network_up)
1241a4e88c60Smartin config_network(0);
1242043e812bSmartin #endif
1243043e812bSmartin server.xfer = rv == 1 ? XFER_HTTP : XFER_FTP;
1244043e812bSmartin arg.arg = &server;
1245043e812bSmartin arg.rv = -1;
1246043e812bSmartin msg_display_add_subst(MSG_entropy_via_download, 1, file_desc);
1247043e812bSmartin msg_printf("\n\n");
1248043e812bSmartin process_menu(MENU_entropy_ftpsource, &arg);
1249043e812bSmartin if (arg.rv == SET_RETRY)
1250043e812bSmartin return false;
1251043e812bSmartin make_url(url, &server, entropy_file);
1252043e812bSmartin if (server.xfer == XFER_FTP &&
1253043e812bSmartin strcmp("ftp", server.user) == 0 && server.pass[0] == 0) {
1254043e812bSmartin /* do anon ftp */
1255043e812bSmartin ftp_opt = "-a ";
1256043e812bSmartin } else {
1257043e812bSmartin ftp_opt = "";
1258043e812bSmartin }
1259043e812bSmartin rv = run_program(RUN_DISPLAY | RUN_PROGRESS,
1260043e812bSmartin "/usr/bin/ftp %s -o %s %s",
126178ab2ae0Smartin ftp_opt, tmpf, url);
126278ab2ae0Smartin strcpy(path, tmpf);
1263043e812bSmartin return rv == 0;
1264043e812bSmartin case 3:
1265043e812bSmartin #ifndef DEBUG
1266043e812bSmartin if (!network_up)
1267a4e88c60Smartin config_network(0);
1268043e812bSmartin #endif
1269043e812bSmartin rv = -1;
1270043e812bSmartin msg_display_add_subst(MSG_entropy_via_nfs, 1, file_desc);
1271043e812bSmartin msg_printf("\n\n");
1272043e812bSmartin process_menu(MENU_entropy_nfssource, &rv);
1273043e812bSmartin if (rv == SET_RETRY)
1274043e812bSmartin return false;
1275043e812bSmartin if (nfs_host[0] != 0 && nfs_dir[0] != 0 &&
1276043e812bSmartin entropy_file[0] != 0) {
1277043e812bSmartin strcpy(mountpt, "/tmp/ent-mnt.XXXXXX");
1278043e812bSmartin dir = mkdtemp(mountpt);
1279043e812bSmartin if (dir == NULL)
1280043e812bSmartin return false;
1281043e812bSmartin sprintf(path, "%s/%s", mountpt, entropy_file);
1282043e812bSmartin if (run_program(RUN_SILENT,
1283043e812bSmartin "mount -t nfs -r %s:/%s %s",
1284043e812bSmartin nfs_host, nfs_dir, mountpt) == 0) {
1285043e812bSmartin run_program(RUN_SILENT,
128678ab2ae0Smartin "cp %s %s", path, tmpf);
1287043e812bSmartin run_program(RUN_SILENT,
1288043e812bSmartin "umount %s", mountpt);
1289043e812bSmartin rmdir(mountpt);
129078ab2ae0Smartin strcpy(path, tmpf);
1291043e812bSmartin }
1292043e812bSmartin }
1293043e812bSmartin break;
1294043e812bSmartin case 4:
1295043e812bSmartin rv = -1;
1296043e812bSmartin /* Get device, filesystem, and filepath */
1297043e812bSmartin process_menu (MENU_entropy_localfs, &rv);
1298043e812bSmartin if (rv == SET_RETRY)
1299043e812bSmartin return false;
1300043e812bSmartin if (localfs_dev[0] != 0 && localfs_fs[0] != 0 &&
1301043e812bSmartin entropy_file[0] != 0) {
1302043e812bSmartin strcpy(mountpt, "/tmp/ent-mnt.XXXXXX");
1303043e812bSmartin dir = mkdtemp(mountpt);
1304043e812bSmartin if (dir == NULL)
1305043e812bSmartin return false;
1306043e812bSmartin sprintf(path, "%s/%s", mountpt, entropy_file);
1307043e812bSmartin if (run_program(RUN_SILENT,
1308043e812bSmartin "mount -t %s -r /dev/%s %s",
1309043e812bSmartin localfs_fs, localfs_dev, mountpt) == 0) {
1310043e812bSmartin run_program(RUN_SILENT,
131178ab2ae0Smartin "cp %s %s", path, tmpf);
1312043e812bSmartin run_program(RUN_SILENT,
1313043e812bSmartin "umount %s", mountpt);
1314043e812bSmartin rmdir(mountpt);
131578ab2ae0Smartin strcpy(path, tmpf);
1316043e812bSmartin }
1317043e812bSmartin }
1318043e812bSmartin break;
1319043e812bSmartin }
1320043e812bSmartin return path[0] != 0;
1321043e812bSmartin }
1322043e812bSmartin
1323043e812bSmartin static void
entropy_add_bin_file(void)1324043e812bSmartin entropy_add_bin_file(void)
1325043e812bSmartin {
1326043e812bSmartin char fname[PATH_MAX];
1327043e812bSmartin
1328043e812bSmartin if (!entropy_get_file(false, fname))
1329043e812bSmartin return;
1330043e812bSmartin if (access(fname, R_OK) == 0)
1331043e812bSmartin run_program(RUN_SILENT, "dd if=%s of=" _PATH_RANDOM,
1332043e812bSmartin fname);
1333043e812bSmartin }
1334043e812bSmartin
1335043e812bSmartin static void
entropy_add_seed(void)1336043e812bSmartin entropy_add_seed(void)
1337043e812bSmartin {
1338043e812bSmartin char fname[PATH_MAX];
1339043e812bSmartin
1340043e812bSmartin if (!entropy_get_file(true, fname))
1341043e812bSmartin return;
1342043e812bSmartin if (access(fname, R_OK) == 0)
1343043e812bSmartin run_program(RUN_SILENT, "rndctl -L %s", fname);
1344043e812bSmartin }
1345043e812bSmartin
1346043e812bSmartin /*
1347043e812bSmartin * return true if we have enough entropy
1348043e812bSmartin */
1349043e812bSmartin bool
do_add_entropy(void)135003af0822Smartin do_add_entropy(void)
1351043e812bSmartin {
1352043e812bSmartin int rv;
1353043e812bSmartin
1354043e812bSmartin if (entropy_needed() == 0)
1355043e812bSmartin return true;
1356043e812bSmartin
13571219ba36Smartin for (;;) {
13581219ba36Smartin if (entropy_needed() == 0)
13591219ba36Smartin break;
13601219ba36Smartin
1361043e812bSmartin msg_clear();
1362043e812bSmartin rv = 0;
1363043e812bSmartin process_menu(MENU_not_enough_entropy, &rv);
1364043e812bSmartin switch (rv) {
1365043e812bSmartin case 0:
1366043e812bSmartin return false;
1367043e812bSmartin case 1:
1368043e812bSmartin entropy_add_manual();
1369043e812bSmartin break;
1370043e812bSmartin case 2:
1371043e812bSmartin entropy_add_seed();
1372043e812bSmartin break;
1373043e812bSmartin case 3:
1374043e812bSmartin entropy_add_bin_file();
1375043e812bSmartin break;
1376043e812bSmartin default:
1377043e812bSmartin /*
1378043e812bSmartin * retry after small delay to give a new USB device
1379043e812bSmartin * a chance to attach and do deliver some
1380043e812bSmartin * entropy
1381043e812bSmartin */
1382043e812bSmartin msg_display(".");
1383043e812bSmartin for (size_t i = 0; i < 10; i++) {
1384043e812bSmartin if (entropy_needed() == 0)
1385043e812bSmartin return true;
1386043e812bSmartin sleep(1);
1387043e812bSmartin msg_display_add(".");
1388043e812bSmartin }
1389043e812bSmartin }
1390043e812bSmartin }
13911219ba36Smartin
13921219ba36Smartin /*
13931219ba36Smartin * Save entropy (maybe again) to give the seed file a good
13941219ba36Smartin * entropy estimate.
13951219ba36Smartin */
13961219ba36Smartin run_program(RUN_SILENT | RUN_CHROOT | RUN_ERROR_OK,
13971219ba36Smartin "/etc/rc.d/random_seed stop");
13981219ba36Smartin
13991219ba36Smartin return true;
1400043e812bSmartin }
1401043e812bSmartin #endif
1402043e812bSmartin
1403043e812bSmartin
1404249ed7a6Smartin
140550dbef1aSdholland /*
140650dbef1aSdholland * Get and unpack the distribution.
140750dbef1aSdholland * Show success_msg if installation completes.
140850dbef1aSdholland * Otherwise show failure_msg and wait for the user to ack it before continuing.
140950dbef1aSdholland * success_msg and failure_msg must both be 0-adic messages.
141050dbef1aSdholland */
141150dbef1aSdholland int
get_and_unpack_sets(int update,msg setupdone_msg,msg success_msg,msg failure_msg)141250dbef1aSdholland get_and_unpack_sets(int update, msg setupdone_msg, msg success_msg, msg failure_msg)
141350dbef1aSdholland {
141450dbef1aSdholland distinfo *dist;
141550dbef1aSdholland int status;
141653d0b64dSmartin int set, olderror, oldfound;
14170466f288Smartin bool entropy_loaded = false;
141850dbef1aSdholland
141950dbef1aSdholland /* Ensure mountpoint for distribution files exists in current root. */
142050dbef1aSdholland (void)mkdir("/mnt2", S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
142150dbef1aSdholland if (script)
142250dbef1aSdholland (void)fprintf(script, "mkdir -m 755 /mnt2\n");
142350dbef1aSdholland
142450dbef1aSdholland /* reset failure/success counters */
142550dbef1aSdholland memset(&tarstats, 0, sizeof(tarstats));
142650dbef1aSdholland
142750dbef1aSdholland /* Find out which files to "get" if we get files. */
142850dbef1aSdholland
142950dbef1aSdholland /* Accurately count selected sets */
143050dbef1aSdholland for (dist = dist_list; (set = dist->set) != SET_LAST; dist++) {
1431fe2acef4Schristos if (dist->name == NULL)
1432fe2acef4Schristos continue;
1433249ed7a6Smartin if (set_status[set] & SET_NO_EXTRACT)
1434249ed7a6Smartin continue;
143550dbef1aSdholland if ((set_status[set] & (SET_VALID | SET_SELECTED))
143650dbef1aSdholland == (SET_VALID | SET_SELECTED))
143750dbef1aSdholland tarstats.nselected++;
143850dbef1aSdholland }
143950dbef1aSdholland
144050dbef1aSdholland status = SET_RETRY;
1441fe2acef4Schristos for (dist = dist_list; (set = dist->set) != SET_LAST; dist++) {
144250dbef1aSdholland if (dist->name == NULL)
144350dbef1aSdholland continue;
144450dbef1aSdholland if (set_status[set] != (SET_VALID | SET_SELECTED))
144550dbef1aSdholland continue;
144650dbef1aSdholland
144753d0b64dSmartin /* save stats, in case we will retry */
144853d0b64dSmartin oldfound = tarstats.nfound;
144953d0b64dSmartin olderror = tarstats.nerror;
145053d0b64dSmartin
145150dbef1aSdholland if (status != SET_OK) {
145250dbef1aSdholland /* This might force a redraw.... */
145350dbef1aSdholland clearok(curscr, 1);
145450dbef1aSdholland touchwin(stdscr);
145550dbef1aSdholland wrefresh(stdscr);
145650dbef1aSdholland /* Sort out the location of the set files */
145750dbef1aSdholland do {
145850dbef1aSdholland umount_mnt2();
145924ecf24eSchristos msg_fmt_display(MSG_distmedium, "%d%d%s",
146024ecf24eSchristos tarstats.nselected,
146150dbef1aSdholland tarstats.nsuccess + tarstats.nskipped,
146250dbef1aSdholland dist->name);
146350dbef1aSdholland fetch_fn = NULL;
146450dbef1aSdholland process_menu(MENU_distmedium, &status);
146550dbef1aSdholland } while (status == SET_RETRY);
146650dbef1aSdholland
146750dbef1aSdholland if (status == SET_SKIP) {
146850dbef1aSdholland set_status[set] |= SET_SKIPPED;
146950dbef1aSdholland tarstats.nskipped++;
147050dbef1aSdholland continue;
147150dbef1aSdholland }
147250dbef1aSdholland if (status == SET_SKIP_GROUP) {
147350dbef1aSdholland skip_set(dist, status);
147450dbef1aSdholland continue;
147550dbef1aSdholland }
147650dbef1aSdholland if (status != SET_OK) {
14774103857bSmartin hit_enter_to_continue(failure_msg, NULL);
147850dbef1aSdholland return 1;
147950dbef1aSdholland }
148050dbef1aSdholland }
148150dbef1aSdholland
1482249ed7a6Smartin if (set_status[set] & SET_NO_EXTRACT)
1483249ed7a6Smartin continue;
1484249ed7a6Smartin
148550dbef1aSdholland /* Try to extract this set */
148650dbef1aSdholland status = extract_file(dist, update);
148753d0b64dSmartin if (status == SET_RETRY) {
148853d0b64dSmartin /* do this set again */
148950dbef1aSdholland dist--;
149053d0b64dSmartin /* and reset statistics to what we had before this
149153d0b64dSmartin * set */
149253d0b64dSmartin tarstats.nfound = oldfound;
149353d0b64dSmartin tarstats.nerror = olderror;
149453d0b64dSmartin }
149550dbef1aSdholland }
149650dbef1aSdholland
1497249ed7a6Smartin #ifdef MD_SET_EXTRACT_FINALIZE
1498249ed7a6Smartin MD_SET_EXTRACT_FINALIZE(update);
1499249ed7a6Smartin #endif
1500249ed7a6Smartin
150150dbef1aSdholland if (tarstats.nerror == 0 && tarstats.nsuccess == tarstats.nselected) {
150250dbef1aSdholland msg_display(MSG_endtarok);
150350dbef1aSdholland /* Give user a chance to see the success message */
150450dbef1aSdholland sleep(1);
150550dbef1aSdholland } else {
150650dbef1aSdholland /* We encountered errors. Let the user know. */
150724ecf24eSchristos msg_fmt_display(MSG_endtar, "%d%d%d%d%d%d",
150850dbef1aSdholland tarstats.nselected, tarstats.nnotfound, tarstats.nskipped,
150950dbef1aSdholland tarstats.nfound, tarstats.nsuccess, tarstats.nerror);
15104103857bSmartin hit_enter_to_continue(NULL, NULL);
151150dbef1aSdholland }
151250dbef1aSdholland
151350dbef1aSdholland /*
151450dbef1aSdholland * postinstall needs to be run after extracting all sets, because
151550dbef1aSdholland * otherwise /var/db/obsolete will only have current information
151650dbef1aSdholland * from the base, comp, and etc sets.
151750dbef1aSdholland */
151850dbef1aSdholland if (update && (set_status[SET_ETC] & SET_INSTALLED)) {
151950dbef1aSdholland int oldsendmail;
152050dbef1aSdholland oldsendmail = run_program(RUN_DISPLAY | RUN_CHROOT |
152150dbef1aSdholland RUN_ERROR_OK | RUN_PROGRESS,
152250dbef1aSdholland "/usr/sbin/postinstall -s /.sysinst -d / check mailerconf");
152350dbef1aSdholland if (oldsendmail == 1) {
152450dbef1aSdholland msg_display(MSG_oldsendmail);
1525e21052b4Smartin if (ask_yesno(NULL)) {
152650dbef1aSdholland run_program(RUN_DISPLAY | RUN_CHROOT,
152750dbef1aSdholland "/usr/sbin/postinstall -s /.sysinst -d / fix mailerconf");
152850dbef1aSdholland }
152950dbef1aSdholland }
153050dbef1aSdholland run_program(RUN_DISPLAY | RUN_CHROOT,
153150dbef1aSdholland "/usr/sbin/postinstall -s /.sysinst -d / fix");
1532ea6af427Stls
1533ea6af427Stls /* Don't discard the system's old entropy if any */
1534ea6af427Stls run_program(RUN_CHROOT | RUN_SILENT,
1535ea6af427Stls "/etc/rc.d/random_seed start");
15360466f288Smartin entropy_loaded = true;
153750dbef1aSdholland }
153850dbef1aSdholland
153950dbef1aSdholland /* Configure the system */
1540b3b874d0Sriastradh if (set_status[SET_BASE] & SET_INSTALLED) {
154150dbef1aSdholland run_makedev();
1542b3b874d0Sriastradh if (!update) {
1543b3b874d0Sriastradh run_program(RUN_CHROOT|RUN_DISPLAY,
1544b3b874d0Sriastradh "/usr/sbin/certctl rehash");
1545b3b874d0Sriastradh }
1546b3b874d0Sriastradh }
154750dbef1aSdholland
154803af0822Smartin if (!update) {
1549ea6af427Stls struct stat sb1, sb2;
1550ea6af427Stls
1551722a22e4Smartin if (stat(target_expand("/"), &sb1) == 0
1552722a22e4Smartin && stat(target_expand("/var"), &sb2) == 0
1553722a22e4Smartin && sb1.st_dev != sb2.st_dev) {
1554ea6af427Stls add_rc_conf("random_file=/etc/entropy-file\n");
1555ea6af427Stls if (target_file_exists_p("/boot.cfg")) {
1556ea6af427Stls run_program(RUN_CHROOT|RUN_FATAL,
1557ea6af427Stls "sh -c 'sed -e s./var/db/./etc/. "
1558ea6af427Stls "< /boot.cfg "
1559ea6af427Stls "> /tmp/boot.cfg.tmp'");
1560ea6af427Stls mv_within_target_or_die("/tmp/boot.cfg.tmp",
1561ea6af427Stls "/boot.cfg");
15622f0931afSmartin
1563ea6af427Stls }
1564ea6af427Stls }
1565ea6af427Stls
15662f0931afSmartin #ifdef MD_BOOT_CFG_FINALIZE
15672f0931afSmartin if (target_file_exists_p("/boot.cfg")) {
15682f0931afSmartin MD_BOOT_CFG_FINALIZE("/boot.cfg");
15692f0931afSmartin }
15702f0931afSmartin #endif
15712f0931afSmartin
1572ea6af427Stls /* Save keyboard type */
157350dbef1aSdholland save_kb_encoding();
157450dbef1aSdholland
157550dbef1aSdholland /* Other configuration. */
157650dbef1aSdholland mnt_net_config();
157750dbef1aSdholland }
157850dbef1aSdholland
157950dbef1aSdholland /* Mounted dist dir? */
158050dbef1aSdholland umount_mnt2();
158150dbef1aSdholland
1582043e812bSmartin #ifdef CHECK_ENTROPY
1583043e812bSmartin entropy_loaded |= entropy_needed() == 0;
1584043e812bSmartin #endif
1585043e812bSmartin
1586ea6af427Stls /* Save entropy -- on some systems it's ~all we'll ever get */
15870466f288Smartin if (!update || entropy_loaded)
15880466f288Smartin run_program(RUN_SILENT | RUN_CHROOT | RUN_ERROR_OK,
1589ea6af427Stls "/etc/rc.d/random_seed stop");
159050dbef1aSdholland /* Install/Upgrade complete ... reboot or exit to script */
15914103857bSmartin hit_enter_to_continue(success_msg, NULL);
159250dbef1aSdholland return 0;
159350dbef1aSdholland }
159450dbef1aSdholland
159550dbef1aSdholland void
umount_mnt2(void)159650dbef1aSdholland umount_mnt2(void)
159750dbef1aSdholland {
159850dbef1aSdholland if (!mnt2_mounted)
159950dbef1aSdholland return;
160050dbef1aSdholland run_program(RUN_SILENT, "/sbin/umount /mnt2");
160150dbef1aSdholland mnt2_mounted = 0;
160250dbef1aSdholland }
160350dbef1aSdholland
160450dbef1aSdholland
160550dbef1aSdholland /*
160650dbef1aSdholland * Do a quick sanity check that the target can reboot.
160750dbef1aSdholland * return 1 if everything OK, 0 if there is a problem.
160850dbef1aSdholland * Uses a table of files we expect to find after a base install/upgrade.
160950dbef1aSdholland */
161050dbef1aSdholland
161150dbef1aSdholland /* test flag and pathname to check for after unpacking. */
161250dbef1aSdholland struct check_table { unsigned int mode; const char *path;} checks[] = {
161350dbef1aSdholland { S_IFREG, "/netbsd" },
161450dbef1aSdholland { S_IFDIR, "/etc" },
161550dbef1aSdholland { S_IFREG, "/etc/fstab" },
161650dbef1aSdholland { S_IFREG, "/sbin/init" },
161750dbef1aSdholland { S_IFREG, "/bin/sh" },
161850dbef1aSdholland { S_IFREG, "/etc/rc" },
161950dbef1aSdholland { S_IFREG, "/etc/rc.subr" },
162050dbef1aSdholland { S_IFREG, "/etc/rc.conf" },
162150dbef1aSdholland { S_IFDIR, "/dev" },
162250dbef1aSdholland { S_IFCHR, "/dev/console" },
162350dbef1aSdholland /* XXX check for rootdev in target /dev? */
162450dbef1aSdholland { S_IFREG, "/sbin/fsck" },
162550dbef1aSdholland { S_IFREG, "/sbin/fsck_ffs" },
162650dbef1aSdholland { S_IFREG, "/sbin/mount" },
162750dbef1aSdholland { S_IFREG, "/sbin/mount_ffs" },
162850dbef1aSdholland { S_IFREG, "/sbin/mount_nfs" },
162950dbef1aSdholland #if defined(DEBUG) || defined(DEBUG_CHECK)
163050dbef1aSdholland { S_IFREG, "/foo/bar" }, /* bad entry to exercise warning */
163150dbef1aSdholland #endif
163250dbef1aSdholland { 0, 0 }
163350dbef1aSdholland
163450dbef1aSdholland };
163550dbef1aSdholland
163650dbef1aSdholland /*
163750dbef1aSdholland * Check target for a single file.
163850dbef1aSdholland */
163950dbef1aSdholland static int
check_for(unsigned int mode,const char * pathname)164050dbef1aSdholland check_for(unsigned int mode, const char *pathname)
164150dbef1aSdholland {
164250dbef1aSdholland int found;
164350dbef1aSdholland
164450dbef1aSdholland found = (target_test(mode, pathname) == 0);
164550dbef1aSdholland if (found == 0)
164624ecf24eSchristos msg_fmt_display(MSG_rootmissing, "%s", pathname);
164750dbef1aSdholland return found;
164850dbef1aSdholland }
164950dbef1aSdholland
165050dbef1aSdholland /*
165150dbef1aSdholland * Check that all the files in check_table are present in the
165250dbef1aSdholland * target root. Warn if not found.
165350dbef1aSdholland */
165450dbef1aSdholland int
sanity_check(void)165550dbef1aSdholland sanity_check(void)
165650dbef1aSdholland {
165750dbef1aSdholland int target_ok = 1;
165850dbef1aSdholland struct check_table *p;
165950dbef1aSdholland
166050dbef1aSdholland for (p = checks; p->path; p++) {
166150dbef1aSdholland target_ok = target_ok && check_for(p->mode, p->path);
166250dbef1aSdholland }
166350dbef1aSdholland if (target_ok)
166450dbef1aSdholland return 0;
166550dbef1aSdholland
166650dbef1aSdholland /* Uh, oh. Something's missing. */
16674103857bSmartin hit_enter_to_continue(MSG_badroot, NULL);
166850dbef1aSdholland return 1;
166950dbef1aSdholland }
167050dbef1aSdholland
167150dbef1aSdholland /*
167250dbef1aSdholland * Some globals to pass things back from callbacks
167350dbef1aSdholland */
167450dbef1aSdholland static char zoneinfo_dir[STRSIZE];
167550dbef1aSdholland static int zonerootlen;
167650dbef1aSdholland static char *tz_selected; /* timezonename (relative to share/zoneinfo */
167750dbef1aSdholland const char *tz_default; /* UTC, or whatever /etc/localtime points to */
167850dbef1aSdholland static char tz_env[STRSIZE];
167950dbef1aSdholland static int save_cursel, save_topline;
168022988562Smartin static int time_menu = -1;
168122988562Smartin
168222988562Smartin static void
update_time_display(void)168322988562Smartin update_time_display(void)
168422988562Smartin {
168522988562Smartin time_t t;
168622988562Smartin struct tm *tm;
168722988562Smartin char cur_time[STRSIZE], *p;
168822988562Smartin
168922988562Smartin t = time(NULL);
169022988562Smartin tm = localtime(&t);
169122988562Smartin strlcpy(cur_time, safectime(&t), sizeof cur_time);
169222988562Smartin p = strchr(cur_time, '\n');
169322988562Smartin if (p != NULL)
169422988562Smartin *p = 0;
169522988562Smartin
169622988562Smartin msg_clear();
169722988562Smartin msg_fmt_table_add(MSG_choose_timezone, "%s%s%s%s",
169822988562Smartin tz_default, tz_selected, cur_time, tm ? tm->tm_zone : "?");
169922988562Smartin }
170050dbef1aSdholland
170150dbef1aSdholland /*
170250dbef1aSdholland * Callback from timezone menu
170350dbef1aSdholland */
170450dbef1aSdholland static int
set_tz_select(menudesc * m,void * arg)170550dbef1aSdholland set_tz_select(menudesc *m, void *arg)
170650dbef1aSdholland {
170750dbef1aSdholland char *new;
170850dbef1aSdholland
170950dbef1aSdholland if (m && strcmp(tz_selected, m->opts[m->cursel].opt_name) != 0) {
171050dbef1aSdholland /* Change the displayed timezone */
171150dbef1aSdholland new = strdup(m->opts[m->cursel].opt_name);
171250dbef1aSdholland if (new == NULL)
171350dbef1aSdholland return 0;
171450dbef1aSdholland free(tz_selected);
171550dbef1aSdholland tz_selected = new;
171650dbef1aSdholland snprintf(tz_env, sizeof tz_env, "%.*s%s",
171750dbef1aSdholland zonerootlen, zoneinfo_dir, tz_selected);
171850dbef1aSdholland setenv("TZ", tz_env, 1);
171950dbef1aSdholland }
172050dbef1aSdholland if (m)
172150dbef1aSdholland /* Warp curser to 'Exit' line on menu */
172250dbef1aSdholland m->cursel = -1;
172350dbef1aSdholland
172422988562Smartin update_time_display();
172522988562Smartin if (time_menu >= 1) {
172622988562Smartin WINDOW *w = get_menudesc(time_menu)->mw;
172722988562Smartin if (w != NULL) {
172822988562Smartin touchwin(w);
172922988562Smartin wrefresh(w);
173022988562Smartin }
173122988562Smartin }
173250dbef1aSdholland return 0;
173350dbef1aSdholland }
173450dbef1aSdholland
173550dbef1aSdholland static int
set_tz_back(menudesc * m,void * arg)173650dbef1aSdholland set_tz_back(menudesc *m, void *arg)
173750dbef1aSdholland {
173850dbef1aSdholland
173950dbef1aSdholland zoneinfo_dir[zonerootlen] = 0;
174050dbef1aSdholland m->cursel = save_cursel;
174150dbef1aSdholland m->topline = save_topline;
174250dbef1aSdholland return 0;
174350dbef1aSdholland }
174450dbef1aSdholland
174550dbef1aSdholland static int
set_tz_dir(menudesc * m,void * arg)174650dbef1aSdholland set_tz_dir(menudesc *m, void *arg)
174750dbef1aSdholland {
174850dbef1aSdholland
174950dbef1aSdholland strlcpy(zoneinfo_dir + zonerootlen, m->opts[m->cursel].opt_name,
175050dbef1aSdholland sizeof zoneinfo_dir - zonerootlen);
175150dbef1aSdholland save_cursel = m->cursel;
175250dbef1aSdholland save_topline = m->topline;
175350dbef1aSdholland m->cursel = 0;
175450dbef1aSdholland m->topline = 0;
175550dbef1aSdholland return 0;
175650dbef1aSdholland }
175750dbef1aSdholland
175850dbef1aSdholland /*
175950dbef1aSdholland * Alarm-handler to update example-display
176050dbef1aSdholland */
176150dbef1aSdholland static void
176250dbef1aSdholland /*ARGSUSED*/
timezone_sig(int sig)176350dbef1aSdholland timezone_sig(int sig)
176450dbef1aSdholland {
176550dbef1aSdholland
176650dbef1aSdholland set_tz_select(NULL, NULL);
176750dbef1aSdholland alarm(60);
176850dbef1aSdholland }
176950dbef1aSdholland
177050dbef1aSdholland static int
tz_sort(const void * a,const void * b)177150dbef1aSdholland tz_sort(const void *a, const void *b)
177250dbef1aSdholland {
177350dbef1aSdholland return strcmp(((const menu_ent *)a)->opt_name, ((const menu_ent *)b)->opt_name);
177450dbef1aSdholland }
177550dbef1aSdholland
177650dbef1aSdholland static void
tzm_set_names(menudesc * m,void * arg)177750dbef1aSdholland tzm_set_names(menudesc *m, void *arg)
177850dbef1aSdholland {
177950dbef1aSdholland DIR *dir;
178050dbef1aSdholland struct dirent *dp;
178150dbef1aSdholland static int nfiles;
178250dbef1aSdholland static int maxfiles = 32;
178350dbef1aSdholland static menu_ent *tz_menu;
178450dbef1aSdholland static char **tz_names;
178550dbef1aSdholland void *p;
178650dbef1aSdholland int maxfname;
178750dbef1aSdholland char *fp;
178850dbef1aSdholland struct stat sb;
178950dbef1aSdholland
179050dbef1aSdholland if (tz_menu == NULL)
1791ce713491Schristos tz_menu = calloc(maxfiles, sizeof *tz_menu);
179250dbef1aSdholland if (tz_names == NULL)
179350dbef1aSdholland tz_names = malloc(maxfiles * sizeof *tz_names);
179450dbef1aSdholland if (tz_menu == NULL || tz_names == NULL)
179550dbef1aSdholland return; /* error - skip timezone setting */
179650dbef1aSdholland while (nfiles > 0)
179750dbef1aSdholland free(tz_names[--nfiles]);
179850dbef1aSdholland
179950dbef1aSdholland dir = opendir(zoneinfo_dir);
180050dbef1aSdholland fp = strchr(zoneinfo_dir, 0);
180150dbef1aSdholland if (fp != zoneinfo_dir + zonerootlen) {
180250dbef1aSdholland tz_names[0] = 0;
180350dbef1aSdholland tz_menu[0].opt_name = msg_string(MSG_tz_back);
180450dbef1aSdholland tz_menu[0].opt_action = set_tz_back;
180550dbef1aSdholland nfiles = 1;
180650dbef1aSdholland }
180750dbef1aSdholland maxfname = zoneinfo_dir + sizeof zoneinfo_dir - fp - 1;
180850dbef1aSdholland if (dir != NULL) {
180950dbef1aSdholland while ((dp = readdir(dir)) != NULL) {
181050dbef1aSdholland if (dp->d_namlen > maxfname || dp->d_name[0] == '.')
181150dbef1aSdholland continue;
181250dbef1aSdholland strlcpy(fp, dp->d_name, maxfname);
181350dbef1aSdholland if (stat(zoneinfo_dir, &sb) == -1)
181450dbef1aSdholland continue;
181550dbef1aSdholland if (nfiles >= maxfiles) {
18169caaf9d7Smartin p = realloc(tz_menu,
18179caaf9d7Smartin 2 * maxfiles * sizeof *tz_menu);
181850dbef1aSdholland if (p == NULL)
181950dbef1aSdholland break;
182050dbef1aSdholland tz_menu = p;
18219caaf9d7Smartin memset(tz_menu + maxfiles, 0,
18229caaf9d7Smartin maxfiles * sizeof *tz_menu);
18239caaf9d7Smartin p = realloc(tz_names,
18249caaf9d7Smartin 2 * maxfiles * sizeof *tz_names);
182550dbef1aSdholland if (p == NULL)
182650dbef1aSdholland break;
182750dbef1aSdholland tz_names = p;
18289caaf9d7Smartin memset(tz_names + maxfiles, 0,
18299caaf9d7Smartin maxfiles * sizeof *tz_names);
183050dbef1aSdholland maxfiles *= 2;
183150dbef1aSdholland }
183250dbef1aSdholland if (S_ISREG(sb.st_mode))
183350dbef1aSdholland tz_menu[nfiles].opt_action = set_tz_select;
183450dbef1aSdholland else if (S_ISDIR(sb.st_mode)) {
183550dbef1aSdholland tz_menu[nfiles].opt_action = set_tz_dir;
183650dbef1aSdholland strlcat(fp, "/",
183750dbef1aSdholland sizeof(zoneinfo_dir) - (fp - zoneinfo_dir));
183850dbef1aSdholland } else
183950dbef1aSdholland continue;
184050dbef1aSdholland tz_names[nfiles] = strdup(zoneinfo_dir + zonerootlen);
184150dbef1aSdholland tz_menu[nfiles].opt_name = tz_names[nfiles];
184250dbef1aSdholland nfiles++;
184350dbef1aSdholland }
184450dbef1aSdholland closedir(dir);
184550dbef1aSdholland }
184650dbef1aSdholland *fp = 0;
184750dbef1aSdholland
184850dbef1aSdholland m->opts = tz_menu;
184950dbef1aSdholland m->numopts = nfiles;
185050dbef1aSdholland qsort(tz_menu, nfiles, sizeof *tz_menu, tz_sort);
185150dbef1aSdholland }
185250dbef1aSdholland
185350dbef1aSdholland void
get_tz_default(void)185450dbef1aSdholland get_tz_default(void)
185550dbef1aSdholland {
185650dbef1aSdholland char localtime_link[STRSIZE];
185750dbef1aSdholland static char localtime_target[STRSIZE];
185850dbef1aSdholland int rc;
185950dbef1aSdholland
186050dbef1aSdholland strlcpy(localtime_link, target_expand("/etc/localtime"),
186150dbef1aSdholland sizeof localtime_link);
186250dbef1aSdholland
186350dbef1aSdholland /* Add sanity check that /mnt/usr/share/zoneinfo contains
186450dbef1aSdholland * something useful
186550dbef1aSdholland */
186650dbef1aSdholland
186750dbef1aSdholland rc = readlink(localtime_link, localtime_target,
186850dbef1aSdholland sizeof(localtime_target) - 1);
186950dbef1aSdholland if (rc < 0) {
187050dbef1aSdholland /* error, default to UTC */
187150dbef1aSdholland tz_default = "UTC";
187250dbef1aSdholland } else {
187350dbef1aSdholland localtime_target[rc] = '\0';
187450dbef1aSdholland tz_default = strchr(strstr(localtime_target, "zoneinfo"), '/') + 1;
187550dbef1aSdholland }
187650dbef1aSdholland }
187750dbef1aSdholland
187850dbef1aSdholland /*
187950dbef1aSdholland * Choose from the files in usr/share/zoneinfo and set etc/localtime
188050dbef1aSdholland */
188150dbef1aSdholland int
set_timezone(void)188250dbef1aSdholland set_timezone(void)
188350dbef1aSdholland {
188450dbef1aSdholland char localtime_link[STRSIZE];
188550dbef1aSdholland char localtime_target[STRSIZE];
188650dbef1aSdholland int menu_no;
188750dbef1aSdholland
188850dbef1aSdholland strlcpy(zoneinfo_dir, target_expand("/usr/share/zoneinfo/"),
188950dbef1aSdholland sizeof zoneinfo_dir - 1);
189050dbef1aSdholland zonerootlen = strlen(zoneinfo_dir);
189150dbef1aSdholland
189250dbef1aSdholland get_tz_default();
189350dbef1aSdholland
189450dbef1aSdholland tz_selected = strdup(tz_default);
189550dbef1aSdholland snprintf(tz_env, sizeof(tz_env), "%s%s", zoneinfo_dir, tz_selected);
189650dbef1aSdholland setenv("TZ", tz_env, 1);
189722988562Smartin update_time_display();
189850dbef1aSdholland
189950dbef1aSdholland signal(SIGALRM, timezone_sig);
190050dbef1aSdholland alarm(60);
190150dbef1aSdholland
190250dbef1aSdholland menu_no = new_menu(NULL, NULL, 14, 23, 9,
190350dbef1aSdholland 12, 32, MC_ALWAYS_SCROLL | MC_NOSHORTCUT,
190450dbef1aSdholland tzm_set_names, NULL, NULL,
19057ca7eecaSmartin "\nPlease consult the install documents.",
19067ca7eecaSmartin MSG_exit_menu_generic);
1907fa635f7dSmartin if (menu_no >= 0) {
190822988562Smartin time_menu = menu_no;
190950dbef1aSdholland process_menu(menu_no, NULL);
191022988562Smartin time_menu = -1;
191150dbef1aSdholland
191250dbef1aSdholland free_menu(menu_no);
1913fa635f7dSmartin }
191450dbef1aSdholland
1915fa635f7dSmartin alarm(0);
191650dbef1aSdholland signal(SIGALRM, SIG_IGN);
191750dbef1aSdholland
1918fa635f7dSmartin if (menu_no >= 0) {
191950dbef1aSdholland snprintf(localtime_target, sizeof(localtime_target),
192050dbef1aSdholland "/usr/share/zoneinfo/%s", tz_selected);
192150dbef1aSdholland strlcpy(localtime_link, target_expand("/etc/localtime"),
192250dbef1aSdholland sizeof localtime_link);
192350dbef1aSdholland unlink(localtime_link);
192450dbef1aSdholland symlink(localtime_target, localtime_link);
1925fa635f7dSmartin }
192650dbef1aSdholland
192750dbef1aSdholland return 1;
192850dbef1aSdholland }
192950dbef1aSdholland
193050dbef1aSdholland void
scripting_vfprintf(FILE * f,const char * fmt,va_list ap)193150dbef1aSdholland scripting_vfprintf(FILE *f, const char *fmt, va_list ap)
193250dbef1aSdholland {
19332ab231eeSmartin va_list ap2;
193450dbef1aSdholland
19352ab231eeSmartin va_copy(ap2, ap);
193650dbef1aSdholland if (f)
193750dbef1aSdholland (void)vfprintf(f, fmt, ap);
193850dbef1aSdholland if (script)
19392ab231eeSmartin (void)vfprintf(script, fmt, ap2);
194050dbef1aSdholland }
194150dbef1aSdholland
194250dbef1aSdholland void
scripting_fprintf(FILE * f,const char * fmt,...)194350dbef1aSdholland scripting_fprintf(FILE *f, const char *fmt, ...)
194450dbef1aSdholland {
194550dbef1aSdholland va_list ap;
194650dbef1aSdholland
194750dbef1aSdholland va_start(ap, fmt);
194850dbef1aSdholland scripting_vfprintf(f, fmt, ap);
194950dbef1aSdholland va_end(ap);
195050dbef1aSdholland }
195150dbef1aSdholland
195250dbef1aSdholland void
add_rc_conf(const char * fmt,...)195350dbef1aSdholland add_rc_conf(const char *fmt, ...)
195450dbef1aSdholland {
195550dbef1aSdholland FILE *f;
195650dbef1aSdholland va_list ap;
195750dbef1aSdholland
195850dbef1aSdholland va_start(ap, fmt);
195950dbef1aSdholland f = target_fopen("/etc/rc.conf", "a");
196050dbef1aSdholland if (f != 0) {
196150dbef1aSdholland scripting_fprintf(NULL, "cat <<EOF >>%s/etc/rc.conf\n",
196250dbef1aSdholland target_prefix());
196350dbef1aSdholland scripting_vfprintf(f, fmt, ap);
196450dbef1aSdholland fclose(f);
196550dbef1aSdholland scripting_fprintf(NULL, "EOF\n");
196650dbef1aSdholland }
196750dbef1aSdholland va_end(ap);
196850dbef1aSdholland }
196950dbef1aSdholland
197050dbef1aSdholland int
del_rc_conf(const char * value)197150dbef1aSdholland del_rc_conf(const char *value)
197250dbef1aSdholland {
197350dbef1aSdholland FILE *fp, *nfp;
197450dbef1aSdholland char buf[4096]; /* Ridiculously high, but should be enough in any way */
197550dbef1aSdholland char *rcconf, *tempname = NULL, *bakname = NULL;
197650dbef1aSdholland char *cp;
197750dbef1aSdholland int done = 0;
197850dbef1aSdholland int fd;
197950dbef1aSdholland int retval = 0;
198050dbef1aSdholland
198150dbef1aSdholland /* The paths might seem strange, but using /tmp would require copy instead
198250dbef1aSdholland * of rename operations. */
198350dbef1aSdholland if (asprintf(&rcconf, "%s", target_expand("/etc/rc.conf")) < 0
198450dbef1aSdholland || asprintf(&tempname, "%s", target_expand("/etc/rc.conf.tmp.XXXXXX")) < 0
198550dbef1aSdholland || asprintf(&bakname, "%s", target_expand("/etc/rc.conf.bak.XXXXXX")) < 0) {
198650dbef1aSdholland if (rcconf)
198750dbef1aSdholland free(rcconf);
198850dbef1aSdholland if (tempname)
198950dbef1aSdholland free(tempname);
199024ecf24eSchristos msg_fmt_display(MSG_rcconf_delete_failed, "%s", value);
19914103857bSmartin hit_enter_to_continue(NULL, NULL);
199250dbef1aSdholland return -1;
199350dbef1aSdholland }
199450dbef1aSdholland
199550dbef1aSdholland if ((fd = mkstemp(bakname)) < 0) {
199624ecf24eSchristos msg_fmt_display(MSG_rcconf_delete_failed, "%s", value);
19974103857bSmartin hit_enter_to_continue(NULL, NULL);
199850dbef1aSdholland return -1;
199950dbef1aSdholland }
200050dbef1aSdholland close(fd);
200150dbef1aSdholland
200250dbef1aSdholland if (!(fp = fopen(rcconf, "r+")) || (fd = mkstemp(tempname)) < 0) {
200350dbef1aSdholland if (fp)
200450dbef1aSdholland fclose(fp);
200524ecf24eSchristos msg_fmt_display(MSG_rcconf_delete_failed, "%s", value);
20064103857bSmartin hit_enter_to_continue(NULL, NULL);
200750dbef1aSdholland return -1;
200850dbef1aSdholland }
200950dbef1aSdholland
201050dbef1aSdholland nfp = fdopen(fd, "w");
201150dbef1aSdholland if (!nfp) {
201250dbef1aSdholland fclose(fp);
201350dbef1aSdholland close(fd);
201424ecf24eSchristos msg_fmt_display(MSG_rcconf_delete_failed, "%s", value);
20154103857bSmartin hit_enter_to_continue(NULL, NULL);
201650dbef1aSdholland return -1;
201750dbef1aSdholland }
201850dbef1aSdholland
201950dbef1aSdholland while (fgets(buf, sizeof buf, fp) != NULL) {
202050dbef1aSdholland
202150dbef1aSdholland cp = buf + strspn(buf, " \t"); /* Skip initial spaces */
202250dbef1aSdholland if (strncmp(cp, value, strlen(value)) == 0) {
202350dbef1aSdholland cp += strlen(value);
202450dbef1aSdholland if (*cp != '=')
202550dbef1aSdholland scripting_fprintf(nfp, "%s", buf);
202650dbef1aSdholland else
202750dbef1aSdholland done = 1;
202850dbef1aSdholland } else {
202950dbef1aSdholland scripting_fprintf(nfp, "%s", buf);
203050dbef1aSdholland }
203150dbef1aSdholland }
203250dbef1aSdholland fclose(fp);
203350dbef1aSdholland fclose(nfp);
203450dbef1aSdholland
203550dbef1aSdholland if (done) {
203650dbef1aSdholland if (rename(rcconf, bakname)) {
203750dbef1aSdholland msg_display(MSG_rcconf_backup_failed);
2038e21052b4Smartin if (!ask_noyes(NULL)) {
203950dbef1aSdholland retval = -1;
204050dbef1aSdholland goto done;
204150dbef1aSdholland }
204250dbef1aSdholland }
204350dbef1aSdholland
204450dbef1aSdholland if (rename(tempname, rcconf)) {
204550dbef1aSdholland if (rename(bakname, rcconf)) {
20464103857bSmartin hit_enter_to_continue(MSG_rcconf_restore_failed,
20474103857bSmartin NULL);
204850dbef1aSdholland } else {
20494103857bSmartin hit_enter_to_continue(MSG_rcconf_delete_failed,
20504103857bSmartin NULL);
205150dbef1aSdholland }
205250dbef1aSdholland } else {
205350dbef1aSdholland (void)unlink(bakname);
205450dbef1aSdholland }
205550dbef1aSdholland }
205650dbef1aSdholland
205750dbef1aSdholland done:
205850dbef1aSdholland (void)unlink(tempname);
205950dbef1aSdholland free(rcconf);
206050dbef1aSdholland free(tempname);
206150dbef1aSdholland free(bakname);
206250dbef1aSdholland return retval;
206350dbef1aSdholland }
206450dbef1aSdholland
206550dbef1aSdholland void
add_sysctl_conf(const char * fmt,...)206650dbef1aSdholland add_sysctl_conf(const char *fmt, ...)
206750dbef1aSdholland {
206850dbef1aSdholland FILE *f;
206950dbef1aSdholland va_list ap;
207050dbef1aSdholland
207150dbef1aSdholland va_start(ap, fmt);
207250dbef1aSdholland f = target_fopen("/etc/sysctl.conf", "a");
207350dbef1aSdholland if (f != 0) {
207450dbef1aSdholland scripting_fprintf(NULL, "cat <<EOF >>%s/etc/sysctl.conf\n",
207550dbef1aSdholland target_prefix());
207650dbef1aSdholland scripting_vfprintf(f, fmt, ap);
207750dbef1aSdholland fclose(f);
207850dbef1aSdholland scripting_fprintf(NULL, "EOF\n");
207950dbef1aSdholland }
208050dbef1aSdholland va_end(ap);
208150dbef1aSdholland }
208250dbef1aSdholland
208350dbef1aSdholland void
enable_rc_conf(void)208450dbef1aSdholland enable_rc_conf(void)
208550dbef1aSdholland {
208650dbef1aSdholland
208750dbef1aSdholland replace("/etc/rc.conf", "s/^rc_configured=NO/rc_configured=YES/");
208850dbef1aSdholland }
208950dbef1aSdholland
209050dbef1aSdholland int
check_lfs_progs(void)209150dbef1aSdholland check_lfs_progs(void)
209250dbef1aSdholland {
209350dbef1aSdholland
209450dbef1aSdholland #ifndef NO_LFS
20954b2364d9Smartin return binary_available("fsck_lfs") && binary_available("mount_lfs")
20964b2364d9Smartin && binary_available("newfs_lfs");
209750dbef1aSdholland #else
209850dbef1aSdholland return 0;
209950dbef1aSdholland #endif
210050dbef1aSdholland }
210150dbef1aSdholland
210250dbef1aSdholland int
set_is_source(const char * set_name)210350dbef1aSdholland set_is_source(const char *set_name) {
210450dbef1aSdholland int len = strlen(set_name);
210550dbef1aSdholland return len >= 3 && memcmp(set_name + len - 3, "src", 3) == 0;
210650dbef1aSdholland }
210750dbef1aSdholland
210850dbef1aSdholland const char *
set_dir_for_set(const char * set_name)210950dbef1aSdholland set_dir_for_set(const char *set_name) {
211050dbef1aSdholland if (strcmp(set_name, "pkgsrc") == 0)
211150dbef1aSdholland return pkgsrc_dir;
211250dbef1aSdholland return set_is_source(set_name) ? set_dir_src : set_dir_bin;
211350dbef1aSdholland }
211450dbef1aSdholland
211550dbef1aSdholland const char *
ext_dir_for_set(const char * set_name)211650dbef1aSdholland ext_dir_for_set(const char *set_name) {
211750dbef1aSdholland if (strcmp(set_name, "pkgsrc") == 0)
211850dbef1aSdholland return ext_dir_pkgsrc;
211950dbef1aSdholland return set_is_source(set_name) ? ext_dir_src : ext_dir_bin;
212050dbef1aSdholland }
212150dbef1aSdholland
21224b2364d9Smartin void
do_coloring(unsigned int fg,unsigned int bg)21234b2364d9Smartin do_coloring(unsigned int fg, unsigned int bg) {
21244b2364d9Smartin if (bg > COLOR_WHITE)
21254b2364d9Smartin bg = COLOR_BLUE;
21264b2364d9Smartin if (fg > COLOR_WHITE)
21274b2364d9Smartin fg = COLOR_WHITE;
21284b2364d9Smartin if (fg != bg && has_colors()) {
21294b2364d9Smartin init_pair(1, fg, bg);
21304b2364d9Smartin wbkgd(stdscr, COLOR_PAIR(1));
21314b2364d9Smartin wbkgd(mainwin, COLOR_PAIR(1));
21324b2364d9Smartin wattrset(stdscr, COLOR_PAIR(1));
21334b2364d9Smartin wattrset(mainwin, COLOR_PAIR(1));
21344b2364d9Smartin }
21354b2364d9Smartin /* redraw screen */
21364b2364d9Smartin touchwin(stdscr);
21374b2364d9Smartin touchwin(mainwin);
21384b2364d9Smartin wrefresh(stdscr);
21394b2364d9Smartin wrefresh(mainwin);
21404b2364d9Smartin return;
21414b2364d9Smartin }
21424b2364d9Smartin
21434b2364d9Smartin int
set_menu_select(menudesc * m,void * arg)21444b2364d9Smartin set_menu_select(menudesc *m, void *arg)
21454b2364d9Smartin {
21464b2364d9Smartin *(int *)arg = m->cursel;
21474b2364d9Smartin return 1;
21484b2364d9Smartin }
21494b2364d9Smartin
21504b2364d9Smartin /*
215137a23ecfSmsaitoh * check whether a binary is available somewhere in PATH,
21524b2364d9Smartin * return 1 if found, 0 if not.
21534b2364d9Smartin */
21544103857bSmartin static int
binary_available(const char * prog)21554b2364d9Smartin binary_available(const char *prog)
21564b2364d9Smartin {
2157c623d359Skamil char *p, tmp[MAXPATHLEN], *path = getenv("PATH"), *opath;
21584b2364d9Smartin
21594b2364d9Smartin if (path == NULL)
21604b2364d9Smartin return access(prog, X_OK) == 0;
21614b2364d9Smartin path = strdup(path);
21624b2364d9Smartin if (path == NULL)
21634b2364d9Smartin return 0;
21644b2364d9Smartin
2165c623d359Skamil opath = path;
2166c623d359Skamil
21674b2364d9Smartin while ((p = strsep(&path, ":")) != NULL) {
21684b2364d9Smartin if (strlcpy(tmp, p, MAXPATHLEN) >= MAXPATHLEN)
21694b2364d9Smartin continue;
21704b2364d9Smartin if (strlcat(tmp, "/", MAXPATHLEN) >= MAXPATHLEN)
21714b2364d9Smartin continue;
21724b2364d9Smartin if (strlcat(tmp, prog, MAXPATHLEN) >= MAXPATHLEN)
21734b2364d9Smartin continue;
21744b2364d9Smartin if (access(tmp, X_OK) == 0) {
2175c623d359Skamil free(opath);
21764b2364d9Smartin return 1;
21774b2364d9Smartin }
21784b2364d9Smartin }
2179c623d359Skamil free(opath);
21804b2364d9Smartin return 0;
21814b2364d9Smartin }
21824b2364d9Smartin
2183e47dca20Schristos const char *
safectime(time_t * t)2184e47dca20Schristos safectime(time_t *t)
2185e47dca20Schristos {
2186e47dca20Schristos const char *s = ctime(t);
2187e47dca20Schristos if (s != NULL)
2188e47dca20Schristos return s;
2189e47dca20Schristos
2190e47dca20Schristos // Debugging.
2191e47dca20Schristos fprintf(stderr, "Can't convert to localtime 0x%jx (%s)\n",
2192e47dca20Schristos (intmax_t)*t, strerror(errno));
2193e47dca20Schristos /*123456789012345678901234*/
2194e47dca20Schristos return "preposterous clock time\n";
2195e47dca20Schristos }
2196e21052b4Smartin
2197e21052b4Smartin int
ask_yesno(const char * msgtxt)21985270515fSmartin ask_yesno(const char* msgtxt)
2199e21052b4Smartin {
2200e21052b4Smartin arg_rv p;
2201e21052b4Smartin
2202b77ea2f7Sjoerg p.arg = __UNCONST(msgtxt);
2203e21052b4Smartin p.rv = -1;
2204e21052b4Smartin
2205e21052b4Smartin process_menu(MENU_yesno, &p);
2206e21052b4Smartin return p.rv;
2207e21052b4Smartin }
2208e21052b4Smartin
2209e21052b4Smartin int
ask_noyes(const char * msgtxt)22105270515fSmartin ask_noyes(const char *msgtxt)
2211e21052b4Smartin {
2212e21052b4Smartin arg_rv p;
2213e21052b4Smartin
2214b77ea2f7Sjoerg p.arg = __UNCONST(msgtxt);
2215e21052b4Smartin p.rv = -1;
2216e21052b4Smartin
2217e21052b4Smartin process_menu(MENU_noyes, &p);
2218e21052b4Smartin return p.rv;
2219e21052b4Smartin }
22200ef20e92Smartin
22214103857bSmartin int
ask_reedit(const struct disk_partitions * parts)22224103857bSmartin ask_reedit(const struct disk_partitions *parts)
22234103857bSmartin {
22244103857bSmartin const char *args[2];
22254103857bSmartin arg_rep_int arg;
22264103857bSmartin
22274103857bSmartin args[0] = msg_string(parts->pscheme->name);
22284103857bSmartin args[1] = msg_string(parts->pscheme->short_name);
22294103857bSmartin arg.args.argv = args;
22304103857bSmartin arg.args.argc = 2;
22314103857bSmartin arg.rv = 0;
22324103857bSmartin process_menu(MENU_reedit, &arg);
22334103857bSmartin
22344103857bSmartin return arg.rv;
22354103857bSmartin }
22364103857bSmartin
22370ef20e92Smartin bool
use_tgz_for_set(const char * set_name)22380ef20e92Smartin use_tgz_for_set(const char *set_name)
22390ef20e92Smartin {
22400ef20e92Smartin const struct distinfo *dist;
22410ef20e92Smartin
22420ef20e92Smartin for (dist = dist_list; dist->set != SET_LAST; dist++) {
22430ef20e92Smartin if (dist->name == NULL)
22440ef20e92Smartin continue;
22450ef20e92Smartin if (strcmp(set_name, dist->name) == 0)
22460ef20e92Smartin return dist->force_tgz;
22470ef20e92Smartin }
22480ef20e92Smartin
2249b57ba1ecSmartin return true;
22500ef20e92Smartin }
22510ef20e92Smartin
22520ef20e92Smartin /* Return the postfix used for a given set */
2253b57ba1ecSmartin const char *
set_postfix(const char * set_name)2254b57ba1ecSmartin set_postfix(const char *set_name)
22550ef20e92Smartin {
22560ef20e92Smartin return use_tgz_for_set(set_name) ? dist_tgz_postfix : dist_postfix;
22570ef20e92Smartin }
22580ef20e92Smartin
2259ac730b51Smartin /*
2260b978e7a9Smartin * Replace positional arguments (encoded as $0 .. $N) in the string
2261b978e7a9Smartin * passed by the contents of the passed argument array.
2262b978e7a9Smartin * Caller must free() the result string.
2263ac730b51Smartin */
2264b978e7a9Smartin char*
str_arg_subst(const char * src,size_t argc,const char ** argv)2265b978e7a9Smartin str_arg_subst(const char *src, size_t argc, const char **argv)
2266ac730b51Smartin {
2267b978e7a9Smartin const char *p, *last;
2268ac730b51Smartin char *out, *t;
2269ac730b51Smartin size_t len;
2270ac730b51Smartin
2271ac730b51Smartin len = strlen(src);
2272ac730b51Smartin for (p = strchr(src, '$'); p; p = strchr(p+1, '$')) {
2273ac730b51Smartin char *endp = NULL;
2274ac730b51Smartin size_t n;
2275ac730b51Smartin int e;
2276ac730b51Smartin
2277ac730b51Smartin /* $ followed by a correct numeric position? */
2278ac730b51Smartin n = strtou(p+1, &endp, 10, 0, INT_MAX, &e);
2279ac730b51Smartin if ((e == 0 || e == ENOTSUP) && n < argc) {
2280b978e7a9Smartin len += strlen(argv[n]);
2281ac730b51Smartin len -= endp-p;
2282ac730b51Smartin p = endp-1;
2283ac730b51Smartin }
2284ac730b51Smartin }
2285ac730b51Smartin
2286ac730b51Smartin out = malloc(len+1);
2287b978e7a9Smartin if (out == NULL)
2288b978e7a9Smartin return NULL;
2289ac730b51Smartin
2290ac730b51Smartin t = out;
2291ac730b51Smartin for (last = src, p = strchr(src, '$'); p; p = strchr(p+1, '$')) {
2292ac730b51Smartin char *endp = NULL;
2293ac730b51Smartin size_t n;
2294ac730b51Smartin int e;
2295ac730b51Smartin
2296ac730b51Smartin /* $ followed by a correct numeric position? */
2297ac730b51Smartin n = strtou(p+1, &endp, 10, 0, INT_MAX, &e);
2298ac730b51Smartin if ((e == 0 || e == ENOTSUP) && n < argc) {
2299ac730b51Smartin size_t l = p-last;
2300ac730b51Smartin memcpy(t, last, l);
2301ac730b51Smartin t += l;
2302b978e7a9Smartin strcpy(t, argv[n]);
2303b978e7a9Smartin t += strlen(argv[n]);
2304ac730b51Smartin last = endp;
2305ac730b51Smartin }
2306ac730b51Smartin }
2307ac730b51Smartin if (*last) {
2308ac730b51Smartin strcpy(t, last);
2309ac730b51Smartin t += strlen(last);
2310ac730b51Smartin } else {
2311ac730b51Smartin *t = 0;
2312ac730b51Smartin }
2313ac730b51Smartin assert((size_t)(t-out) == len);
2314ac730b51Smartin
2315b978e7a9Smartin return out;
2316b978e7a9Smartin }
2317ac730b51Smartin
2318b978e7a9Smartin /*
23194103857bSmartin * Does this string have any positional args that need expanding?
2320b978e7a9Smartin */
23214103857bSmartin bool
needs_expanding(const char * src,size_t argc)23224103857bSmartin needs_expanding(const char *src, size_t argc)
2323b978e7a9Smartin {
23244103857bSmartin const char *p;
23254103857bSmartin
23264103857bSmartin for (p = strchr(src, '$'); p; p = strchr(p+1, '$')) {
23274103857bSmartin char *endp = NULL;
23284103857bSmartin size_t n;
23294103857bSmartin int e;
23304103857bSmartin
23314103857bSmartin /* $ followed by a correct numeric position? */
23324103857bSmartin n = strtou(p+1, &endp, 10, 0, INT_MAX, &e);
23334103857bSmartin if ((e == 0 || e == ENOTSUP) && n < argc)
23344103857bSmartin return true;
23354103857bSmartin }
23364103857bSmartin return false;
23374103857bSmartin }
23384103857bSmartin
23394103857bSmartin /*
23404103857bSmartin * Replace positional arguments (encoded as $0 .. $N) in the
23414103857bSmartin * message by the strings passed as ... and call outfunc
23424103857bSmartin * with the result.
23434103857bSmartin */
23444103857bSmartin static void
msg_display_subst_internal(void (* outfunc)(msg),const char * master,size_t argc,va_list ap)234524ecf24eSchristos msg_display_subst_internal(void (*outfunc)(msg),
234624ecf24eSchristos const char *master, size_t argc, va_list ap)
23474103857bSmartin {
2348b978e7a9Smartin const char **args, **arg;
2349b978e7a9Smartin char *out;
2350b978e7a9Smartin
235124ecf24eSchristos args = calloc(argc, sizeof(*args));
2352b978e7a9Smartin if (args == NULL)
2353b978e7a9Smartin return;
2354b978e7a9Smartin
2355b978e7a9Smartin arg = args;
2356b978e7a9Smartin for (size_t i = 0; i < argc; i++)
2357b978e7a9Smartin *arg++ = va_arg(ap, const char*);
2358b978e7a9Smartin
2359b978e7a9Smartin out = str_arg_subst(msg_string(master), argc, args);
2360b978e7a9Smartin if (out != NULL) {
23614103857bSmartin outfunc(out);
2362ac730b51Smartin free(out);
2363b978e7a9Smartin }
2364ac730b51Smartin free(args);
2365ac730b51Smartin }
2366ac730b51Smartin
23674103857bSmartin /*
23684103857bSmartin * Replace positional arguments (encoded as $0 .. $N) in the
23694103857bSmartin * message by the strings passed as ...
23704103857bSmartin */
23714103857bSmartin void
msg_display_subst(const char * master,size_t argc,...)23724103857bSmartin msg_display_subst(const char *master, size_t argc, ...)
23734103857bSmartin {
23744103857bSmartin va_list ap;
23754103857bSmartin
23764103857bSmartin va_start(ap, argc);
23774103857bSmartin msg_display_subst_internal(msg_display, master, argc, ap);
23784103857bSmartin va_end(ap);
23794103857bSmartin }
23804103857bSmartin
23814103857bSmartin /*
23824103857bSmartin * Same as above, but add to message instead of starting a new one
23834103857bSmartin */
23844103857bSmartin void
msg_display_add_subst(const char * master,size_t argc,...)23854103857bSmartin msg_display_add_subst(const char *master, size_t argc, ...)
23864103857bSmartin {
23874103857bSmartin va_list ap;
23884103857bSmartin
23894103857bSmartin va_start(ap, argc);
23904103857bSmartin msg_display_subst_internal(msg_display_add, master, argc, ap);
23914103857bSmartin va_end(ap);
23924103857bSmartin }
23934103857bSmartin
23944103857bSmartin /* initialize have_* variables */
23954103857bSmartin void
check_available_binaries(void)239670b74d30Stsutsui check_available_binaries(void)
23974103857bSmartin {
23984103857bSmartin static int did_test = false;
23994103857bSmartin
24004103857bSmartin if (did_test) return;
24014103857bSmartin did_test = 1;
24024103857bSmartin
24034103857bSmartin have_raid = binary_available("raidctl");
24044103857bSmartin have_vnd = binary_available("vndconfig");
24054103857bSmartin have_cgd = binary_available("cgdconfig");
24064103857bSmartin have_lvm = binary_available("lvm");
24074103857bSmartin have_gpt = binary_available("gpt");
24084103857bSmartin have_dk = binary_available("dkctl");
24094103857bSmartin }
24104103857bSmartin
24114103857bSmartin /*
24124103857bSmartin * Wait for enter and immediately clear the screen after user response
24134103857bSmartin * (in case some longer action follows, so the user has instant feedback)
24144103857bSmartin */
24154103857bSmartin void
hit_enter_to_continue(const char * prompt,const char * title)24164103857bSmartin hit_enter_to_continue(const char *prompt, const char *title)
24174103857bSmartin {
24184103857bSmartin if (prompt != NULL)
24194103857bSmartin msg_display(prompt);
24204103857bSmartin process_menu(MENU_ok, __UNCONST(title));
24214103857bSmartin msg_clear();
24224103857bSmartin wrefresh(mainwin);
24234103857bSmartin }
24244103857bSmartin
24254103857bSmartin /*
24264103857bSmartin * On auto pilot:
24274103857bSmartin * convert an existing set of partitions ot a list of part_usage_info
24284103857bSmartin * so that we "want" exactly what is there already.
24294103857bSmartin */
24304103857bSmartin static bool
usage_info_list_from_parts(struct part_usage_info ** list,size_t * count,struct disk_partitions * parts)24314103857bSmartin usage_info_list_from_parts(struct part_usage_info **list, size_t *count,
24324103857bSmartin struct disk_partitions *parts)
24334103857bSmartin {
24344103857bSmartin struct disk_part_info info;
24354103857bSmartin part_id pno;
24364103857bSmartin size_t no, num;
24374103857bSmartin
24384103857bSmartin num = 0;
24394103857bSmartin for (pno = 0; pno < parts->num_part; pno++) {
24404103857bSmartin if (!parts->pscheme->get_part_info(parts, pno, &info))
24414103857bSmartin continue;
24424103857bSmartin num++;
24434103857bSmartin }
24444103857bSmartin
24454103857bSmartin *list = calloc(num, sizeof(**list));
24464103857bSmartin if (*list == NULL)
24474103857bSmartin return false;
24484103857bSmartin
24494103857bSmartin *count = num;
24504103857bSmartin for (no = pno = 0; pno < parts->num_part && no < num; pno++) {
24514103857bSmartin if (!parts->pscheme->get_part_info(parts, pno, &info))
24524103857bSmartin continue;
24534103857bSmartin (*list)[no].size = info.size;
24544103857bSmartin if (info.last_mounted != NULL && *info.last_mounted != 0) {
24554103857bSmartin strlcpy((*list)[no].mount, info.last_mounted,
24564103857bSmartin sizeof((*list)[no].mount));
24574103857bSmartin (*list)[no].instflags |= PUIINST_MOUNT;
24584103857bSmartin }
24594103857bSmartin (*list)[no].parts = parts;
24604103857bSmartin (*list)[no].cur_part_id = pno;
24614103857bSmartin (*list)[no].cur_start = info.start;
24624103857bSmartin (*list)[no].cur_flags = info.flags;
24634103857bSmartin (*list)[no].type = info.nat_type->generic_ptype;
24644103857bSmartin if ((*list)[no].type == PT_swap) {
24654103857bSmartin (*list)[no].fs_type = FS_SWAP;
24664103857bSmartin (*list)[no].fs_version = 0;
24674103857bSmartin } else {
24684103857bSmartin (*list)[no].fs_type = info.fs_type;
24694103857bSmartin (*list)[no].fs_version = info.fs_sub_type;
24704103857bSmartin }
2471cb429b90Smartin (*list)[no].fs_opt1 = info.fs_opt1;
2472cb429b90Smartin (*list)[no].fs_opt2 = info.fs_opt2;
2473cb429b90Smartin (*list)[no].fs_opt3 = info.fs_opt3;
24744103857bSmartin no++;
24754103857bSmartin }
24764103857bSmartin return true;
24774103857bSmartin }
24784103857bSmartin
24794103857bSmartin bool
empty_usage_set_from_parts(struct partition_usage_set * wanted,struct disk_partitions * parts)2480ec5e52a9Smartin empty_usage_set_from_parts(struct partition_usage_set *wanted,
2481ec5e52a9Smartin struct disk_partitions *parts)
2482ec5e52a9Smartin {
2483bd887569Smartin usage_set_from_parts(wanted, parts);
2484ec5e52a9Smartin return true;
2485ec5e52a9Smartin }
2486ec5e52a9Smartin
2487ec5e52a9Smartin bool
usage_set_from_parts(struct partition_usage_set * wanted,struct disk_partitions * parts)24884103857bSmartin usage_set_from_parts(struct partition_usage_set *wanted,
24894103857bSmartin struct disk_partitions *parts)
24904103857bSmartin {
24914103857bSmartin memset(wanted, 0, sizeof(*wanted));
24924103857bSmartin wanted->parts = parts;
24934103857bSmartin
24944103857bSmartin return usage_info_list_from_parts(&wanted->infos, &wanted->num, parts);
24954103857bSmartin }
24964103857bSmartin
2497c38850fbSmartin bool
usage_set_from_install_desc(struct partition_usage_set * pset,const struct install_partition_desc * install,struct disk_partitions * parts)2498c38850fbSmartin usage_set_from_install_desc(struct partition_usage_set *pset,
2499c38850fbSmartin const struct install_partition_desc *install,
2500c38850fbSmartin struct disk_partitions *parts)
2501c38850fbSmartin {
2502c38850fbSmartin size_t cnt, i;
2503c38850fbSmartin
2504c38850fbSmartin memset(pset, 0, sizeof(*pset));
2505c38850fbSmartin pset->parts = parts;
2506c38850fbSmartin
2507c38850fbSmartin if (!install->infos || !install->num)
2508c38850fbSmartin return false;
2509c38850fbSmartin
2510c38850fbSmartin for (cnt = 0, i = 0; i < install->num; i++) {
2511c38850fbSmartin if (install->infos[i].parts != parts)
2512c38850fbSmartin continue;
2513c38850fbSmartin cnt++;
2514c38850fbSmartin }
2515c38850fbSmartin if (!cnt)
2516c38850fbSmartin return false;
2517c38850fbSmartin pset->num = cnt;
2518c38850fbSmartin pset->infos = calloc(cnt, sizeof(*pset->infos));
2519c38850fbSmartin if (!pset->infos)
2520c38850fbSmartin return false;
2521c38850fbSmartin for (cnt = 0, i = 0; i < install->num; i++) {
2522c38850fbSmartin if (install->infos[i].parts != parts)
2523c38850fbSmartin continue;
2524c38850fbSmartin pset->infos[cnt] = install->infos[i];
2525c38850fbSmartin cnt++;
2526c38850fbSmartin }
2527c38850fbSmartin return true;
2528c38850fbSmartin }
2529c38850fbSmartin
2530c38850fbSmartin bool
merge_usage_set_into_install_desc(struct install_partition_desc * install,const struct partition_usage_set * pset)2531c38850fbSmartin merge_usage_set_into_install_desc(struct install_partition_desc *install,
2532c38850fbSmartin const struct partition_usage_set *pset)
2533c38850fbSmartin {
2534c38850fbSmartin // XXX
2535c38850fbSmartin return false;
2536c38850fbSmartin }
2537c38850fbSmartin
2538f77b58b1Smartin struct disk_partitions *
get_inner_parts(struct disk_partitions * parts)2539f77b58b1Smartin get_inner_parts(struct disk_partitions *parts)
25404103857bSmartin {
2541bfaf0e51Smartin daddr_t start, size;
2542bfaf0e51Smartin part_id pno;
2543bfaf0e51Smartin struct disk_part_info info;
2544bfaf0e51Smartin
2545f77b58b1Smartin if (parts->pscheme->secondary_scheme == NULL)
2546f77b58b1Smartin return NULL;
25474103857bSmartin
2548bfaf0e51Smartin start = -1;
2549bfaf0e51Smartin size = -1;
2550f77b58b1Smartin if (parts->pscheme->guess_install_target == NULL ||
2551f77b58b1Smartin !parts->pscheme->guess_install_target(parts, &start, &size)) {
2552bfaf0e51Smartin for (pno = 0; pno < parts->num_part; pno++) {
2553f77b58b1Smartin if (!parts->pscheme->get_part_info(parts, pno, &info))
2554bfaf0e51Smartin continue;
2555bfaf0e51Smartin if (!(info.flags & PTI_SEC_CONTAINER))
2556bfaf0e51Smartin continue;
2557bfaf0e51Smartin start = info.start;
2558bfaf0e51Smartin size = info.size;
2559bfaf0e51Smartin }
2560bfaf0e51Smartin }
2561f77b58b1Smartin
2562f77b58b1Smartin if (size > 0)
2563f77b58b1Smartin return parts->pscheme->secondary_partitions(parts, start,
2564f77b58b1Smartin false);
2565f77b58b1Smartin
2566f77b58b1Smartin return NULL;
2567f77b58b1Smartin }
2568f77b58b1Smartin
2569f77b58b1Smartin bool
install_desc_from_parts(struct install_partition_desc * install,struct disk_partitions * parts)2570f77b58b1Smartin install_desc_from_parts(struct install_partition_desc *install,
2571f77b58b1Smartin struct disk_partitions *parts)
2572f77b58b1Smartin {
2573f77b58b1Smartin struct disk_partitions *inner_parts;
2574f77b58b1Smartin
2575f77b58b1Smartin memset(install, 0, sizeof(*install));
2576f77b58b1Smartin inner_parts = get_inner_parts(parts);
2577bfaf0e51Smartin if (inner_parts != NULL)
2578bfaf0e51Smartin parts = inner_parts;
2579bfaf0e51Smartin
25804103857bSmartin return usage_info_list_from_parts(&install->infos, &install->num,
25814103857bSmartin parts);
25824103857bSmartin }
25834103857bSmartin
25844103857bSmartin void
free_usage_set(struct partition_usage_set * wanted)25854103857bSmartin free_usage_set(struct partition_usage_set *wanted)
25864103857bSmartin {
2587f77b58b1Smartin /* XXX - free parts? free clone src? */
2588194d5a77Smartin free(wanted->write_back);
25894103857bSmartin free(wanted->menu_opts);
25904103857bSmartin free(wanted->infos);
25914103857bSmartin }
25924103857bSmartin
25934103857bSmartin void
free_install_desc(struct install_partition_desc * install)25944103857bSmartin free_install_desc(struct install_partition_desc *install)
25954103857bSmartin {
2596f77b58b1Smartin size_t i, j;
2597f77b58b1Smartin
25988bb96d39Smartin #ifndef NO_CLONES
2599f77b58b1Smartin for (i = 0; i < install->num; i++) {
2600f77b58b1Smartin struct selected_partitions *src = install->infos[i].clone_src;
2601f77b58b1Smartin if (!(install->infos[i].flags & PUIFLG_CLONE_PARTS) ||
2602f77b58b1Smartin src == NULL)
2603f77b58b1Smartin continue;
2604f77b58b1Smartin free_selected_partitions(src);
2605f77b58b1Smartin for (j = i+1; j < install->num; j++)
2606f77b58b1Smartin if (install->infos[j].clone_src == src)
2607f77b58b1Smartin install->infos[j].clone_src = NULL;
2608f77b58b1Smartin }
2609485d5309Smartin #endif
26108bb96d39Smartin
26118bb96d39Smartin for (i = 0; i < install->num; i++) {
26128bb96d39Smartin struct disk_partitions * parts = install->infos[i].parts;
26138bb96d39Smartin
26148bb96d39Smartin if (parts == NULL)
26158bb96d39Smartin continue;
26168bb96d39Smartin
26178bb96d39Smartin if (parts->pscheme->free)
26188bb96d39Smartin parts->pscheme->free(parts);
26198bb96d39Smartin
26208bb96d39Smartin /* NULL all other references to this parts */
26218bb96d39Smartin for (j = i+1; j < install->num; j++)
26228bb96d39Smartin if (install->infos[j].parts == parts)
26238bb96d39Smartin install->infos[j].parts = NULL;
26248bb96d39Smartin }
26258bb96d39Smartin
2626194d5a77Smartin free(install->write_back);
26274103857bSmartin free(install->infos);
26284103857bSmartin }
26294103857bSmartin
2630249ed7a6Smartin #ifdef MD_MAY_SWAP_TO
2631249ed7a6Smartin bool
may_swap_if_not_sdmmc(const char * disk)2632249ed7a6Smartin may_swap_if_not_sdmmc(const char *disk)
2633249ed7a6Smartin {
2634249ed7a6Smartin int fd, res;
2635249ed7a6Smartin prop_dictionary_t command_dict, args_dict, results_dict, data_dict;
2636249ed7a6Smartin prop_string_t string;
2637249ed7a6Smartin prop_number_t number;
2638249ed7a6Smartin const char *parent = "";
2639249ed7a6Smartin
2640249ed7a6Smartin fd = open(DRVCTLDEV, O_RDONLY, 0);
2641249ed7a6Smartin if (fd == -1)
2642249ed7a6Smartin return true;
2643249ed7a6Smartin
2644249ed7a6Smartin command_dict = prop_dictionary_create();
2645249ed7a6Smartin args_dict = prop_dictionary_create();
2646249ed7a6Smartin
264778ab2ae0Smartin string = prop_string_create_nocopy("get-properties");
2648249ed7a6Smartin prop_dictionary_set(command_dict, "drvctl-command", string);
2649249ed7a6Smartin prop_object_release(string);
2650249ed7a6Smartin
265178ab2ae0Smartin string = prop_string_create_copy(disk);
2652249ed7a6Smartin prop_dictionary_set(args_dict, "device-name", string);
2653249ed7a6Smartin prop_object_release(string);
2654249ed7a6Smartin
2655249ed7a6Smartin prop_dictionary_set(command_dict, "drvctl-arguments",
2656249ed7a6Smartin args_dict);
2657249ed7a6Smartin prop_object_release(args_dict);
2658249ed7a6Smartin
2659249ed7a6Smartin res = prop_dictionary_sendrecv_ioctl(command_dict, fd,
2660249ed7a6Smartin DRVCTLCOMMAND, &results_dict);
2661249ed7a6Smartin prop_object_release(command_dict);
2662249ed7a6Smartin close(fd);
2663249ed7a6Smartin if (res)
2664249ed7a6Smartin return true;
2665249ed7a6Smartin
2666249ed7a6Smartin number = prop_dictionary_get(results_dict, "drvctl-error");
266778ab2ae0Smartin if (prop_number_signed_value(number) == 0) {
2668249ed7a6Smartin data_dict = prop_dictionary_get(results_dict,
2669249ed7a6Smartin "drvctl-result-data");
2670249ed7a6Smartin if (data_dict != NULL) {
2671249ed7a6Smartin string = prop_dictionary_get(data_dict,
2672249ed7a6Smartin "device-parent");
2673249ed7a6Smartin if (string != NULL)
267478ab2ae0Smartin parent = prop_string_value(string);
2675249ed7a6Smartin }
2676249ed7a6Smartin }
2677249ed7a6Smartin
2678249ed7a6Smartin prop_object_release(results_dict);
2679249ed7a6Smartin
2680249ed7a6Smartin if (parent == NULL)
2681249ed7a6Smartin return true;
2682249ed7a6Smartin
2683249ed7a6Smartin return strncmp(parent, "sdmmc", 5) != 0;
2684249ed7a6Smartin }
2685249ed7a6Smartin #endif
2686