12118f387SNathan Whitehorn /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31de7b4b8SPedro F. Giffuni * 42118f387SNathan Whitehorn * Copyright (c) 2011 Nathan Whitehorn 52118f387SNathan Whitehorn * All rights reserved. 62118f387SNathan Whitehorn * 72118f387SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 82118f387SNathan Whitehorn * modification, are permitted provided that the following conditions 92118f387SNathan Whitehorn * are met: 102118f387SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 112118f387SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 122118f387SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 132118f387SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 142118f387SNathan Whitehorn * documentation and/or other materials provided with the distribution. 152118f387SNathan Whitehorn * 162118f387SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 172118f387SNathan Whitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 182118f387SNathan Whitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 192118f387SNathan Whitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 202118f387SNathan Whitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 212118f387SNathan Whitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 222118f387SNathan Whitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 232118f387SNathan Whitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 242118f387SNathan Whitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 252118f387SNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 262118f387SNathan Whitehorn * SUCH DAMAGE. 272118f387SNathan Whitehorn * 282118f387SNathan Whitehorn * $FreeBSD$ 292118f387SNathan Whitehorn */ 302118f387SNathan Whitehorn 312118f387SNathan Whitehorn #include <sys/param.h> 322118f387SNathan Whitehorn 3350e24496SAlfonso S. Siciliano #include <bsddialog.h> 34a107ddbbSRebecca Cran #include <err.h> 354e7e2cadSEd Schouten #include <errno.h> 364e7e2cadSEd Schouten #include <fstab.h> 374e7e2cadSEd Schouten #include <inttypes.h> 384e7e2cadSEd Schouten #include <libgeom.h> 394e7e2cadSEd Schouten #include <libutil.h> 4050e24496SAlfonso S. Siciliano #include <stdio.h> 414e7e2cadSEd Schouten #include <stdlib.h> 4250e24496SAlfonso S. Siciliano #include <string.h> 43a107ddbbSRebecca Cran #include <sysexits.h> 442118f387SNathan Whitehorn 4550e24496SAlfonso S. Siciliano #include "diskmenu.h" 462118f387SNathan Whitehorn #include "partedit.h" 472118f387SNathan Whitehorn 482118f387SNathan Whitehorn struct pmetadata_head part_metadata; 494f5fcf8dSNathan Whitehorn static int sade_mode = 0; 502118f387SNathan Whitehorn 512118f387SNathan Whitehorn static int apply_changes(struct gmesh *mesh); 527059fa6fSAllan Jude static void apply_workaround(struct gmesh *mesh); 532118f387SNathan Whitehorn static struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems); 542118f387SNathan Whitehorn static void add_geom_children(struct ggeom *gp, int recurse, 552118f387SNathan Whitehorn struct partedit_item **items, int *nitems); 562118f387SNathan Whitehorn static void init_fstab_metadata(void); 572118f387SNathan Whitehorn static void get_mount_points(struct partedit_item *items, int nitems); 582118f387SNathan Whitehorn static int validate_setup(void); 592118f387SNathan Whitehorn 60bcc25b7eSNathan Whitehorn static void 61bcc25b7eSNathan Whitehorn sigint_handler(int sig) 62bcc25b7eSNathan Whitehorn { 63bcc25b7eSNathan Whitehorn struct gmesh mesh; 64bcc25b7eSNathan Whitehorn 65bcc25b7eSNathan Whitehorn /* Revert all changes and exit dialog-mode cleanly on SIGINT */ 66bcc25b7eSNathan Whitehorn geom_gettree(&mesh); 67bcc25b7eSNathan Whitehorn gpart_revert_all(&mesh); 68bcc25b7eSNathan Whitehorn geom_deletetree(&mesh); 69bcc25b7eSNathan Whitehorn 7050e24496SAlfonso S. Siciliano bsddialog_end(); 71bcc25b7eSNathan Whitehorn 72bcc25b7eSNathan Whitehorn exit(1); 73bcc25b7eSNathan Whitehorn } 74bcc25b7eSNathan Whitehorn 752118f387SNathan Whitehorn int 76bcc25b7eSNathan Whitehorn main(int argc, const char **argv) 77bcc25b7eSNathan Whitehorn { 782118f387SNathan Whitehorn struct partition_metadata *md; 79b07b7aecSRyan Moeller const char *progname, *prompt; 8007d76626SNathan Whitehorn struct partedit_item *items = NULL; 812118f387SNathan Whitehorn struct gmesh mesh; 8250e24496SAlfonso S. Siciliano int i, op, nitems; 832118f387SNathan Whitehorn int error; 8450e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 852118f387SNathan Whitehorn 864e7e2cadSEd Schouten progname = getprogname(); 874e7e2cadSEd Schouten if (strcmp(progname, "sade") == 0) 884f5fcf8dSNathan Whitehorn sade_mode = 1; 894f5fcf8dSNathan Whitehorn 902118f387SNathan Whitehorn TAILQ_INIT(&part_metadata); 912118f387SNathan Whitehorn 922118f387SNathan Whitehorn init_fstab_metadata(); 932118f387SNathan Whitehorn 9450e24496SAlfonso S. Siciliano if (bsddialog_init() == BSDDIALOG_ERROR) 9550e24496SAlfonso S. Siciliano err(1, "%s", bsddialog_geterror()); 9650e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 974f5fcf8dSNathan Whitehorn if (!sade_mode) 9850e24496SAlfonso S. Siciliano bsddialog_backtitle(&conf, "FreeBSD Installer"); 9950e24496SAlfonso S. Siciliano i = 0; 1002118f387SNathan Whitehorn 101bcc25b7eSNathan Whitehorn /* Revert changes on SIGINT */ 102bcc25b7eSNathan Whitehorn signal(SIGINT, sigint_handler); 103bcc25b7eSNathan Whitehorn 1044e7e2cadSEd Schouten if (strcmp(progname, "autopart") == 0) { /* Guided */ 1052118f387SNathan Whitehorn prompt = "Please review the disk setup. When complete, press " 106bcc25b7eSNathan Whitehorn "the Finish button."; 1076e15678aSNathan Whitehorn /* Experimental ZFS autopartition support */ 1086e15678aSNathan Whitehorn if (argc > 1 && strcmp(argv[1], "zfs") == 0) { 1096e15678aSNathan Whitehorn part_wizard("zfs"); 1106e15678aSNathan Whitehorn } else { 1116e15678aSNathan Whitehorn part_wizard("ufs"); 1126e15678aSNathan Whitehorn } 1134e7e2cadSEd Schouten } else if (strcmp(progname, "scriptedpart") == 0) { 114f0ddc92dSNathan Whitehorn error = scripted_editor(argc, argv); 1155eca7e06SNathan Whitehorn prompt = NULL; 116f0ddc92dSNathan Whitehorn if (error != 0) { 11750e24496SAlfonso S. Siciliano bsddialog_end(); 118f0ddc92dSNathan Whitehorn return (error); 119f0ddc92dSNathan Whitehorn } 1202118f387SNathan Whitehorn } else { 12150e24496SAlfonso S. Siciliano prompt = "Create partitions for FreeBSD, F1 for help.\n" 12250e24496SAlfonso S. Siciliano "No changes will be made until you select Finish."; 1232118f387SNathan Whitehorn } 1242118f387SNathan Whitehorn 1252118f387SNathan Whitehorn /* Show the part editor either immediately, or to confirm wizard */ 1265eca7e06SNathan Whitehorn while (prompt != NULL) { 12750e24496SAlfonso S. Siciliano bsddialog_clearterminal(); 12850e24496SAlfonso S. Siciliano if (!sade_mode) 12950e24496SAlfonso S. Siciliano bsddialog_backtitle(&conf, "FreeBSD Installer"); 1302118f387SNathan Whitehorn 13107d76626SNathan Whitehorn error = geom_gettree(&mesh); 13207d76626SNathan Whitehorn if (error == 0) 13307d76626SNathan Whitehorn items = read_geom_mesh(&mesh, &nitems); 13407d76626SNathan Whitehorn if (error || items == NULL) { 13550e24496SAlfonso S. Siciliano conf.title = "Error"; 13650e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "No disks found. If you need " 13750e24496SAlfonso S. Siciliano "to install a kernel driver, choose Shell at the " 13850e24496SAlfonso S. Siciliano "installation menu.", 0, 0); 13907d76626SNathan Whitehorn break; 14007d76626SNathan Whitehorn } 14107d76626SNathan Whitehorn 14207d76626SNathan Whitehorn get_mount_points(items, nitems); 14307d76626SNathan Whitehorn 1442118f387SNathan Whitehorn if (i >= nitems) 1452118f387SNathan Whitehorn i = nitems - 1; 14650e24496SAlfonso S. Siciliano op = diskmenu_show("Partition Editor", prompt, items, nitems, 14750e24496SAlfonso S. Siciliano &i); 1482118f387SNathan Whitehorn 1492118f387SNathan Whitehorn switch (op) { 15050e24496SAlfonso S. Siciliano case BUTTON_CREATE: 1512118f387SNathan Whitehorn gpart_create((struct gprovider *)(items[i].cookie), 1522118f387SNathan Whitehorn NULL, NULL, NULL, NULL, 1); 1532118f387SNathan Whitehorn break; 15450e24496SAlfonso S. Siciliano case BUTTON_DELETE: 1552118f387SNathan Whitehorn gpart_delete((struct gprovider *)(items[i].cookie)); 1562118f387SNathan Whitehorn break; 15750e24496SAlfonso S. Siciliano case BUTTON_MODIFY: 1582118f387SNathan Whitehorn gpart_edit((struct gprovider *)(items[i].cookie)); 1592118f387SNathan Whitehorn break; 16050e24496SAlfonso S. Siciliano case BUTTON_REVERT: 1612118f387SNathan Whitehorn gpart_revert_all(&mesh); 1622118f387SNathan Whitehorn while ((md = TAILQ_FIRST(&part_metadata)) != NULL) { 1632118f387SNathan Whitehorn if (md->fstab != NULL) { 1642118f387SNathan Whitehorn free(md->fstab->fs_spec); 1652118f387SNathan Whitehorn free(md->fstab->fs_file); 1662118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 1672118f387SNathan Whitehorn free(md->fstab->fs_mntops); 1682118f387SNathan Whitehorn free(md->fstab->fs_type); 1692118f387SNathan Whitehorn free(md->fstab); 1702118f387SNathan Whitehorn } 1712118f387SNathan Whitehorn if (md->newfs != NULL) 1722118f387SNathan Whitehorn free(md->newfs); 1732118f387SNathan Whitehorn free(md->name); 1742118f387SNathan Whitehorn 1752118f387SNathan Whitehorn TAILQ_REMOVE(&part_metadata, md, metadata); 1762118f387SNathan Whitehorn free(md); 1772118f387SNathan Whitehorn } 1782118f387SNathan Whitehorn init_fstab_metadata(); 1792118f387SNathan Whitehorn break; 18050e24496SAlfonso S. Siciliano case BUTTON_AUTO: 1816e15678aSNathan Whitehorn part_wizard("ufs"); 1822118f387SNathan Whitehorn break; 1832118f387SNathan Whitehorn } 1842118f387SNathan Whitehorn 1852118f387SNathan Whitehorn error = 0; 18650e24496SAlfonso S. Siciliano if (op == BUTTON_FINISH) { 18750e24496SAlfonso S. Siciliano conf.button.ok_label = "Commit"; 18850e24496SAlfonso S. Siciliano conf.button.with_extra = true; 18950e24496SAlfonso S. Siciliano conf.button.extra_label = "Revert & Exit"; 19050e24496SAlfonso S. Siciliano conf.button.cancel_label = "Back"; 19150e24496SAlfonso S. Siciliano conf.title = "Confirmation"; 19250e24496SAlfonso S. Siciliano op = bsddialog_yesno(&conf, "Your changes will now be " 19350e24496SAlfonso S. Siciliano "written to disk. If you have chosen to overwrite " 19450e24496SAlfonso S. Siciliano "existing data, it will be PERMANENTLY ERASED. Are " 19550e24496SAlfonso S. Siciliano "you sure you want to commit your changes?", 0, 0); 19650e24496SAlfonso S. Siciliano conf.button.ok_label = NULL; 19750e24496SAlfonso S. Siciliano conf.button.with_extra = false; 19850e24496SAlfonso S. Siciliano conf.button.extra_label = NULL; 19950e24496SAlfonso S. Siciliano conf.button.cancel_label = NULL; 2002118f387SNathan Whitehorn 20150e24496SAlfonso S. Siciliano if (op == BSDDIALOG_OK && validate_setup()) { /* Save */ 2022118f387SNathan Whitehorn error = apply_changes(&mesh); 2037059fa6fSAllan Jude if (!error) 2047059fa6fSAllan Jude apply_workaround(&mesh); 2052118f387SNathan Whitehorn break; 20650e24496SAlfonso S. Siciliano } else if (op == BSDDIALOG_EXTRA) { /* Quit */ 2072118f387SNathan Whitehorn gpart_revert_all(&mesh); 2082118f387SNathan Whitehorn error = -1; 2092118f387SNathan Whitehorn break; 2102118f387SNathan Whitehorn } 2112118f387SNathan Whitehorn } 2122118f387SNathan Whitehorn 2132118f387SNathan Whitehorn geom_deletetree(&mesh); 2142118f387SNathan Whitehorn free(items); 2152118f387SNathan Whitehorn } 2162118f387SNathan Whitehorn 2175eca7e06SNathan Whitehorn if (prompt == NULL) { 2185eca7e06SNathan Whitehorn error = geom_gettree(&mesh); 2195eca7e06SNathan Whitehorn if (validate_setup()) { 2205eca7e06SNathan Whitehorn error = apply_changes(&mesh); 2215eca7e06SNathan Whitehorn } else { 2225eca7e06SNathan Whitehorn gpart_revert_all(&mesh); 2235eca7e06SNathan Whitehorn error = -1; 2245eca7e06SNathan Whitehorn } 2255eca7e06SNathan Whitehorn } 2262118f387SNathan Whitehorn 2272118f387SNathan Whitehorn geom_deletetree(&mesh); 2282118f387SNathan Whitehorn free(items); 22950e24496SAlfonso S. Siciliano bsddialog_end(); 2302118f387SNathan Whitehorn 2312118f387SNathan Whitehorn return (error); 2322118f387SNathan Whitehorn } 2332118f387SNathan Whitehorn 2342118f387SNathan Whitehorn struct partition_metadata * 2352118f387SNathan Whitehorn get_part_metadata(const char *name, int create) 2362118f387SNathan Whitehorn { 2372118f387SNathan Whitehorn struct partition_metadata *md; 2382118f387SNathan Whitehorn 2392118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) 2402118f387SNathan Whitehorn if (md->name != NULL && strcmp(md->name, name) == 0) 2412118f387SNathan Whitehorn break; 2422118f387SNathan Whitehorn 2432118f387SNathan Whitehorn if (md == NULL && create) { 2442118f387SNathan Whitehorn md = calloc(1, sizeof(*md)); 2452118f387SNathan Whitehorn md->name = strdup(name); 2462118f387SNathan Whitehorn TAILQ_INSERT_TAIL(&part_metadata, md, metadata); 2472118f387SNathan Whitehorn } 2482118f387SNathan Whitehorn 2492118f387SNathan Whitehorn return (md); 2502118f387SNathan Whitehorn } 2512118f387SNathan Whitehorn 2522118f387SNathan Whitehorn void 253bcc25b7eSNathan Whitehorn delete_part_metadata(const char *name) 254bcc25b7eSNathan Whitehorn { 2552118f387SNathan Whitehorn struct partition_metadata *md; 2562118f387SNathan Whitehorn 2572118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 2582118f387SNathan Whitehorn if (md->name != NULL && strcmp(md->name, name) == 0) { 2592118f387SNathan Whitehorn if (md->fstab != NULL) { 2602118f387SNathan Whitehorn free(md->fstab->fs_spec); 2612118f387SNathan Whitehorn free(md->fstab->fs_file); 2622118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 2632118f387SNathan Whitehorn free(md->fstab->fs_mntops); 2642118f387SNathan Whitehorn free(md->fstab->fs_type); 2652118f387SNathan Whitehorn free(md->fstab); 2662118f387SNathan Whitehorn } 2672118f387SNathan Whitehorn if (md->newfs != NULL) 2682118f387SNathan Whitehorn free(md->newfs); 2692118f387SNathan Whitehorn free(md->name); 2702118f387SNathan Whitehorn 2712118f387SNathan Whitehorn TAILQ_REMOVE(&part_metadata, md, metadata); 2722118f387SNathan Whitehorn free(md); 2732118f387SNathan Whitehorn break; 2742118f387SNathan Whitehorn } 2752118f387SNathan Whitehorn } 2762118f387SNathan Whitehorn } 2772118f387SNathan Whitehorn 2782118f387SNathan Whitehorn static int 2792118f387SNathan Whitehorn validate_setup(void) 2802118f387SNathan Whitehorn { 2816fe359f2SNathan Whitehorn struct partition_metadata *md, *root = NULL; 28250e24496SAlfonso S. Siciliano int button; 28350e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 2842118f387SNathan Whitehorn 2852118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 2862118f387SNathan Whitehorn if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) 2876fe359f2SNathan Whitehorn root = md; 2882118f387SNathan Whitehorn 2892118f387SNathan Whitehorn /* XXX: Check for duplicate mountpoints */ 2902118f387SNathan Whitehorn } 2912118f387SNathan Whitehorn 29250e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 29350e24496SAlfonso S. Siciliano 2946fe359f2SNathan Whitehorn if (root == NULL) { 29550e24496SAlfonso S. Siciliano conf.title = "Error"; 29650e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "No root partition was found. " 29750e24496SAlfonso S. Siciliano "The root FreeBSD partition must have a mountpoint " 29850e24496SAlfonso S. Siciliano "of '/'.", 0, 0); 29950e24496SAlfonso S. Siciliano return (false); 3002118f387SNathan Whitehorn } 3012118f387SNathan Whitehorn 3026fe359f2SNathan Whitehorn /* 3036fe359f2SNathan Whitehorn * Check for root partitions that we aren't formatting, which is 3046fe359f2SNathan Whitehorn * usually a mistake 3056fe359f2SNathan Whitehorn */ 3064f5fcf8dSNathan Whitehorn if (root->newfs == NULL && !sade_mode) { 30750e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 30850e24496SAlfonso S. Siciliano conf.title = "Warning"; 30950e24496SAlfonso S. Siciliano button = bsddialog_yesno(&conf, "The chosen root partition " 3106fe359f2SNathan Whitehorn "has a preexisting filesystem. If it contains an existing " 3116fe359f2SNathan Whitehorn "FreeBSD system, please update it with freebsd-update " 3126fe359f2SNathan Whitehorn "instead of installing a new system on it. The partition " 3136fe359f2SNathan Whitehorn "can also be erased by pressing \"No\" and then deleting " 3146fe359f2SNathan Whitehorn "and recreating it. Are you sure you want to proceed?", 3156fe359f2SNathan Whitehorn 0, 0); 31650e24496SAlfonso S. Siciliano if (button == BSDDIALOG_CANCEL) 31750e24496SAlfonso S. Siciliano return (false); 3186fe359f2SNathan Whitehorn } 3196fe359f2SNathan Whitehorn 32050e24496SAlfonso S. Siciliano return (true); 3212118f387SNathan Whitehorn } 3222118f387SNathan Whitehorn 3232118f387SNathan Whitehorn static int 324c2f16c59SNathan Whitehorn mountpoint_sorter(const void *xa, const void *xb) 325c2f16c59SNathan Whitehorn { 326c2f16c59SNathan Whitehorn struct partition_metadata *a = *(struct partition_metadata **)xa; 327c2f16c59SNathan Whitehorn struct partition_metadata *b = *(struct partition_metadata **)xb; 328c2f16c59SNathan Whitehorn 329c2f16c59SNathan Whitehorn if (a->fstab == NULL && b->fstab == NULL) 330c2f16c59SNathan Whitehorn return 0; 331c2f16c59SNathan Whitehorn if (a->fstab == NULL) 332c2f16c59SNathan Whitehorn return 1; 333c2f16c59SNathan Whitehorn if (b->fstab == NULL) 334c2f16c59SNathan Whitehorn return -1; 335c2f16c59SNathan Whitehorn 336c2f16c59SNathan Whitehorn return strcmp(a->fstab->fs_file, b->fstab->fs_file); 337c2f16c59SNathan Whitehorn } 338c2f16c59SNathan Whitehorn 339c2f16c59SNathan Whitehorn static int 3402118f387SNathan Whitehorn apply_changes(struct gmesh *mesh) 3412118f387SNathan Whitehorn { 3422118f387SNathan Whitehorn struct partition_metadata *md; 3432118f387SNathan Whitehorn char message[512]; 34450e24496SAlfonso S. Siciliano int i, nitems, error, *miniperc; 34550e24496SAlfonso S. Siciliano const char **minilabel; 3462118f387SNathan Whitehorn const char *fstab_path; 3472118f387SNathan Whitehorn FILE *fstab; 34850e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 3492118f387SNathan Whitehorn 3502118f387SNathan Whitehorn nitems = 1; /* Partition table changes */ 3512118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 3522118f387SNathan Whitehorn if (md->newfs != NULL) 3532118f387SNathan Whitehorn nitems++; 3542118f387SNathan Whitehorn } 35550e24496SAlfonso S. Siciliano minilabel = calloc(nitems, sizeof(const char *)); 35650e24496SAlfonso S. Siciliano miniperc = calloc(nitems, sizeof(int)); 35750e24496SAlfonso S. Siciliano minilabel[0] = "Writing partition tables"; 35850e24496SAlfonso S. Siciliano miniperc[0] = BSDDIALOG_MG_INPROGRESS; 3592118f387SNathan Whitehorn i = 1; 3602118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 3612118f387SNathan Whitehorn if (md->newfs != NULL) { 3622118f387SNathan Whitehorn char *item; 3632118f387SNathan Whitehorn item = malloc(255); 3642118f387SNathan Whitehorn sprintf(item, "Initializing %s", md->name); 36550e24496SAlfonso S. Siciliano minilabel[i] = item; 36650e24496SAlfonso S. Siciliano miniperc[i] = BSDDIALOG_MG_PENDING; 3672118f387SNathan Whitehorn i++; 3682118f387SNathan Whitehorn } 3692118f387SNathan Whitehorn } 3702118f387SNathan Whitehorn 3712118f387SNathan Whitehorn i = 0; 37250e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 37350e24496SAlfonso S. Siciliano conf.title = "Initializing"; 37450e24496SAlfonso S. Siciliano bsddialog_mixedgauge(&conf, 3752118f387SNathan Whitehorn "Initializing file systems. Please wait.", 0, 0, i * 100 / nitems, 37650e24496SAlfonso S. Siciliano nitems, minilabel, miniperc); 3772118f387SNathan Whitehorn gpart_commit(mesh); 37850e24496SAlfonso S. Siciliano miniperc[i] = BSDDIALOG_MG_COMPLETED; 3792118f387SNathan Whitehorn i++; 3802118f387SNathan Whitehorn 3812118f387SNathan Whitehorn if (getenv("BSDINSTALL_LOG") == NULL) 3822118f387SNathan Whitehorn setenv("BSDINSTALL_LOG", "/dev/null", 1); 3832118f387SNathan Whitehorn 3842118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 3852118f387SNathan Whitehorn if (md->newfs != NULL) { 38650e24496SAlfonso S. Siciliano miniperc[i] = BSDDIALOG_MG_INPROGRESS; 38750e24496SAlfonso S. Siciliano bsddialog_mixedgauge(&conf, 3882118f387SNathan Whitehorn "Initializing file systems. Please wait.", 0, 0, 38950e24496SAlfonso S. Siciliano i * 100 / nitems, nitems, minilabel, miniperc); 3902118f387SNathan Whitehorn sprintf(message, "(echo %s; %s) >>%s 2>>%s", 3912118f387SNathan Whitehorn md->newfs, md->newfs, getenv("BSDINSTALL_LOG"), 3922118f387SNathan Whitehorn getenv("BSDINSTALL_LOG")); 3932118f387SNathan Whitehorn error = system(message); 39450e24496SAlfonso S. Siciliano miniperc[i] = (error == 0) ? 39550e24496SAlfonso S. Siciliano BSDDIALOG_MG_COMPLETED : BSDDIALOG_MG_FAILED; 3962118f387SNathan Whitehorn i++; 3972118f387SNathan Whitehorn } 3982118f387SNathan Whitehorn } 39950e24496SAlfonso S. Siciliano bsddialog_mixedgauge(&conf, "Initializing file systems. Please wait.", 40050e24496SAlfonso S. Siciliano 0, 0, i * 100 / nitems, nitems, minilabel, miniperc); 4012118f387SNathan Whitehorn 4022118f387SNathan Whitehorn for (i = 1; i < nitems; i++) 40350e24496SAlfonso S. Siciliano free(__DECONST(char *, minilabel[i])); 40450e24496SAlfonso S. Siciliano 40550e24496SAlfonso S. Siciliano free(minilabel); 40650e24496SAlfonso S. Siciliano free(miniperc); 4072118f387SNathan Whitehorn 408c2f16c59SNathan Whitehorn /* Sort filesystems for fstab so that mountpoints are ordered */ 409c2f16c59SNathan Whitehorn { 410c2f16c59SNathan Whitehorn struct partition_metadata **tobesorted; 411c2f16c59SNathan Whitehorn struct partition_metadata *tmp; 412c2f16c59SNathan Whitehorn int nparts = 0; 413c2f16c59SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) 414c2f16c59SNathan Whitehorn nparts++; 415c2f16c59SNathan Whitehorn tobesorted = malloc(sizeof(struct partition_metadata *)*nparts); 416c2f16c59SNathan Whitehorn nparts = 0; 417c2f16c59SNathan Whitehorn TAILQ_FOREACH_SAFE(md, &part_metadata, metadata, tmp) { 418c2f16c59SNathan Whitehorn tobesorted[nparts++] = md; 419c2f16c59SNathan Whitehorn TAILQ_REMOVE(&part_metadata, md, metadata); 420c2f16c59SNathan Whitehorn } 421c2f16c59SNathan Whitehorn qsort(tobesorted, nparts, sizeof(tobesorted[0]), 422c2f16c59SNathan Whitehorn mountpoint_sorter); 423c2f16c59SNathan Whitehorn 424c2f16c59SNathan Whitehorn /* Now re-add everything */ 425c2f16c59SNathan Whitehorn while (nparts-- > 0) 426c2f16c59SNathan Whitehorn TAILQ_INSERT_HEAD(&part_metadata, 427c2f16c59SNathan Whitehorn tobesorted[nparts], metadata); 428c2f16c59SNathan Whitehorn free(tobesorted); 429c2f16c59SNathan Whitehorn } 430c2f16c59SNathan Whitehorn 4312118f387SNathan Whitehorn if (getenv("PATH_FSTAB") != NULL) 4322118f387SNathan Whitehorn fstab_path = getenv("PATH_FSTAB"); 4332118f387SNathan Whitehorn else 4342118f387SNathan Whitehorn fstab_path = "/etc/fstab"; 4352118f387SNathan Whitehorn fstab = fopen(fstab_path, "w+"); 4362118f387SNathan Whitehorn if (fstab == NULL) { 4372118f387SNathan Whitehorn sprintf(message, "Cannot open fstab file %s for writing (%s)\n", 4382118f387SNathan Whitehorn getenv("PATH_FSTAB"), strerror(errno)); 43950e24496SAlfonso S. Siciliano conf.title = "Error"; 44050e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, message, 0, 0); 4412118f387SNathan Whitehorn return (-1); 4422118f387SNathan Whitehorn } 4432118f387SNathan Whitehorn fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n"); 4442118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 4452118f387SNathan Whitehorn if (md->fstab != NULL) 44626092385SKevin Lo fprintf(fstab, "%s\t%s\t\t%s\t%s\t%d\t%d\n", 4472118f387SNathan Whitehorn md->fstab->fs_spec, md->fstab->fs_file, 4482118f387SNathan Whitehorn md->fstab->fs_vfstype, md->fstab->fs_mntops, 4492118f387SNathan Whitehorn md->fstab->fs_freq, md->fstab->fs_passno); 4502118f387SNathan Whitehorn } 4512118f387SNathan Whitehorn fclose(fstab); 4522118f387SNathan Whitehorn 4532118f387SNathan Whitehorn return (0); 4542118f387SNathan Whitehorn } 4552118f387SNathan Whitehorn 4567059fa6fSAllan Jude static void 4577059fa6fSAllan Jude apply_workaround(struct gmesh *mesh) 4587059fa6fSAllan Jude { 4597059fa6fSAllan Jude struct gclass *classp; 4607059fa6fSAllan Jude struct ggeom *gp; 4617059fa6fSAllan Jude struct gconfig *gc; 4627059fa6fSAllan Jude const char *scheme = NULL, *modified = NULL; 46350e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 4647059fa6fSAllan Jude 4657059fa6fSAllan Jude LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 4667059fa6fSAllan Jude if (strcmp(classp->lg_name, "PART") == 0) 4677059fa6fSAllan Jude break; 4687059fa6fSAllan Jude } 4697059fa6fSAllan Jude 4707059fa6fSAllan Jude if (strcmp(classp->lg_name, "PART") != 0) { 47150e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 47250e24496SAlfonso S. Siciliano conf.title = "Error"; 47350e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "gpart not found!", 0, 0); 4747059fa6fSAllan Jude return; 4757059fa6fSAllan Jude } 4767059fa6fSAllan Jude 4777059fa6fSAllan Jude LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 4787059fa6fSAllan Jude LIST_FOREACH(gc, &gp->lg_config, lg_config) { 4797059fa6fSAllan Jude if (strcmp(gc->lg_name, "scheme") == 0) { 4807059fa6fSAllan Jude scheme = gc->lg_val; 4817059fa6fSAllan Jude } else if (strcmp(gc->lg_name, "modified") == 0) { 4827059fa6fSAllan Jude modified = gc->lg_val; 4837059fa6fSAllan Jude } 4847059fa6fSAllan Jude } 4857059fa6fSAllan Jude 4867059fa6fSAllan Jude if (scheme && strcmp(scheme, "GPT") == 0 && 4877059fa6fSAllan Jude modified && strcmp(modified, "true") == 0) { 4887059fa6fSAllan Jude if (getenv("WORKAROUND_LENOVO")) 4897059fa6fSAllan Jude gpart_set_root(gp->lg_name, "lenovofix"); 4907059fa6fSAllan Jude if (getenv("WORKAROUND_GPTACTIVE")) 4917059fa6fSAllan Jude gpart_set_root(gp->lg_name, "active"); 4927059fa6fSAllan Jude } 4937059fa6fSAllan Jude } 4947059fa6fSAllan Jude } 4957059fa6fSAllan Jude 4962118f387SNathan Whitehorn static struct partedit_item * 497bcc25b7eSNathan Whitehorn read_geom_mesh(struct gmesh *mesh, int *nitems) 498bcc25b7eSNathan Whitehorn { 4992118f387SNathan Whitehorn struct gclass *classp; 5002118f387SNathan Whitehorn struct ggeom *gp; 5012118f387SNathan Whitehorn struct partedit_item *items; 5022118f387SNathan Whitehorn 5032118f387SNathan Whitehorn *nitems = 0; 5042118f387SNathan Whitehorn items = NULL; 5052118f387SNathan Whitehorn 5062118f387SNathan Whitehorn /* 5072118f387SNathan Whitehorn * Build the device table. First add all disks (and CDs). 5082118f387SNathan Whitehorn */ 5092118f387SNathan Whitehorn 5102118f387SNathan Whitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 5112118f387SNathan Whitehorn if (strcmp(classp->lg_name, "DISK") != 0 && 5122118f387SNathan Whitehorn strcmp(classp->lg_name, "MD") != 0) 5132118f387SNathan Whitehorn continue; 5142118f387SNathan Whitehorn 5152118f387SNathan Whitehorn /* Now recurse into all children */ 5162118f387SNathan Whitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) 5172118f387SNathan Whitehorn add_geom_children(gp, 0, &items, nitems); 5182118f387SNathan Whitehorn } 5192118f387SNathan Whitehorn 5202118f387SNathan Whitehorn return (items); 5212118f387SNathan Whitehorn } 5222118f387SNathan Whitehorn 5232118f387SNathan Whitehorn static void 5242118f387SNathan Whitehorn add_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items, 525bcc25b7eSNathan Whitehorn int *nitems) 526bcc25b7eSNathan Whitehorn { 5272118f387SNathan Whitehorn struct gconsumer *cp; 5282118f387SNathan Whitehorn struct gprovider *pp; 5292118f387SNathan Whitehorn struct gconfig *gc; 5302118f387SNathan Whitehorn 5312118f387SNathan Whitehorn if (strcmp(gp->lg_class->lg_name, "PART") == 0 && 5322118f387SNathan Whitehorn !LIST_EMPTY(&gp->lg_config)) { 5332118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 5342118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) 5352118f387SNathan Whitehorn (*items)[*nitems-1].type = gc->lg_val; 5362118f387SNathan Whitehorn } 5372118f387SNathan Whitehorn } 5382118f387SNathan Whitehorn 5392118f387SNathan Whitehorn if (LIST_EMPTY(&gp->lg_provider)) 5402118f387SNathan Whitehorn return; 5412118f387SNathan Whitehorn 5422118f387SNathan Whitehorn LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 5432118f387SNathan Whitehorn if (strcmp(gp->lg_class->lg_name, "LABEL") == 0) 5442118f387SNathan Whitehorn continue; 5452118f387SNathan Whitehorn 5462118f387SNathan Whitehorn /* Skip WORM media */ 5472118f387SNathan Whitehorn if (strncmp(pp->lg_name, "cd", 2) == 0) 5482118f387SNathan Whitehorn continue; 5492118f387SNathan Whitehorn 5502118f387SNathan Whitehorn *items = realloc(*items, 5512118f387SNathan Whitehorn (*nitems+1)*sizeof(struct partedit_item)); 5522118f387SNathan Whitehorn (*items)[*nitems].indentation = recurse; 5532118f387SNathan Whitehorn (*items)[*nitems].name = pp->lg_name; 5542118f387SNathan Whitehorn (*items)[*nitems].size = pp->lg_mediasize; 5552118f387SNathan Whitehorn (*items)[*nitems].mountpoint = NULL; 5562118f387SNathan Whitehorn (*items)[*nitems].type = ""; 5572118f387SNathan Whitehorn (*items)[*nitems].cookie = pp; 5582118f387SNathan Whitehorn 5592118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 5602118f387SNathan Whitehorn if (strcmp(gc->lg_name, "type") == 0) 5612118f387SNathan Whitehorn (*items)[*nitems].type = gc->lg_val; 5622118f387SNathan Whitehorn } 5632118f387SNathan Whitehorn 5642118f387SNathan Whitehorn /* Skip swap-backed MD devices */ 5652118f387SNathan Whitehorn if (strcmp(gp->lg_class->lg_name, "MD") == 0 && 5662118f387SNathan Whitehorn strcmp((*items)[*nitems].type, "swap") == 0) 5672118f387SNathan Whitehorn continue; 5682118f387SNathan Whitehorn 5692118f387SNathan Whitehorn (*nitems)++; 5702118f387SNathan Whitehorn 5712118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 5722118f387SNathan Whitehorn add_geom_children(cp->lg_geom, recurse+1, items, 5732118f387SNathan Whitehorn nitems); 5742118f387SNathan Whitehorn 5752118f387SNathan Whitehorn /* Only use first provider for acd */ 5762118f387SNathan Whitehorn if (strcmp(gp->lg_class->lg_name, "ACD") == 0) 5772118f387SNathan Whitehorn break; 5782118f387SNathan Whitehorn } 5792118f387SNathan Whitehorn } 5802118f387SNathan Whitehorn 5812118f387SNathan Whitehorn static void 5822118f387SNathan Whitehorn init_fstab_metadata(void) 5832118f387SNathan Whitehorn { 5842118f387SNathan Whitehorn struct fstab *fstab; 5852118f387SNathan Whitehorn struct partition_metadata *md; 5862118f387SNathan Whitehorn 5872118f387SNathan Whitehorn setfsent(); 5882118f387SNathan Whitehorn while ((fstab = getfsent()) != NULL) { 5892118f387SNathan Whitehorn md = calloc(1, sizeof(struct partition_metadata)); 5902118f387SNathan Whitehorn 5912118f387SNathan Whitehorn md->name = NULL; 5922118f387SNathan Whitehorn if (strncmp(fstab->fs_spec, "/dev/", 5) == 0) 5932118f387SNathan Whitehorn md->name = strdup(&fstab->fs_spec[5]); 5942118f387SNathan Whitehorn 5952118f387SNathan Whitehorn md->fstab = malloc(sizeof(struct fstab)); 5962118f387SNathan Whitehorn md->fstab->fs_spec = strdup(fstab->fs_spec); 5972118f387SNathan Whitehorn md->fstab->fs_file = strdup(fstab->fs_file); 5982118f387SNathan Whitehorn md->fstab->fs_vfstype = strdup(fstab->fs_vfstype); 5992118f387SNathan Whitehorn md->fstab->fs_mntops = strdup(fstab->fs_mntops); 6002118f387SNathan Whitehorn md->fstab->fs_type = strdup(fstab->fs_type); 6012118f387SNathan Whitehorn md->fstab->fs_freq = fstab->fs_freq; 6022118f387SNathan Whitehorn md->fstab->fs_passno = fstab->fs_passno; 6032118f387SNathan Whitehorn 6042118f387SNathan Whitehorn md->newfs = NULL; 6052118f387SNathan Whitehorn 6062118f387SNathan Whitehorn TAILQ_INSERT_TAIL(&part_metadata, md, metadata); 6072118f387SNathan Whitehorn } 6082118f387SNathan Whitehorn } 6092118f387SNathan Whitehorn 6102118f387SNathan Whitehorn static void 6112118f387SNathan Whitehorn get_mount_points(struct partedit_item *items, int nitems) 6122118f387SNathan Whitehorn { 6132118f387SNathan Whitehorn struct partition_metadata *md; 6142118f387SNathan Whitehorn int i; 6152118f387SNathan Whitehorn 6162118f387SNathan Whitehorn for (i = 0; i < nitems; i++) { 6172118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 6182118f387SNathan Whitehorn if (md->name != NULL && md->fstab != NULL && 6192118f387SNathan Whitehorn strcmp(md->name, items[i].name) == 0) { 6202118f387SNathan Whitehorn items[i].mountpoint = md->fstab->fs_file; 6212118f387SNathan Whitehorn break; 6222118f387SNathan Whitehorn } 6232118f387SNathan Whitehorn } 6242118f387SNathan Whitehorn } 6252118f387SNathan Whitehorn } 626