12118f387SNathan Whitehorn /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 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 292118f387SNathan Whitehorn #include <sys/param.h> 306e15678aSNathan Whitehorn #include <sys/stat.h> 3150e24496SAlfonso S. Siciliano 3250e24496SAlfonso S. Siciliano #include <bsddialog.h> 3350e24496SAlfonso S. Siciliano #include <ctype.h> 342118f387SNathan Whitehorn #include <errno.h> 35db8b5613SRebecca Cran #include <fcntl.h> 362118f387SNathan Whitehorn #include <libutil.h> 372118f387SNathan Whitehorn #include <inttypes.h> 3850e24496SAlfonso S. Siciliano #include <stdio.h> 3950e24496SAlfonso S. Siciliano #include <stdlib.h> 4050e24496SAlfonso S. Siciliano #include <string.h> 4150e24496SAlfonso S. Siciliano #include <unistd.h> 422118f387SNathan Whitehorn 432118f387SNathan Whitehorn #include <libgeom.h> 442118f387SNathan Whitehorn 452118f387SNathan Whitehorn #include "partedit.h" 462118f387SNathan Whitehorn 472118f387SNathan Whitehorn #define GPART_FLAGS "x" /* Do not commit changes by default */ 482118f387SNathan Whitehorn 492118f387SNathan Whitehorn static void 502118f387SNathan Whitehorn gpart_show_error(const char *title, const char *explanation, const char *errstr) 512118f387SNathan Whitehorn { 522118f387SNathan Whitehorn char *errmsg; 532118f387SNathan Whitehorn char message[512]; 542118f387SNathan Whitehorn int error; 5550e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 562118f387SNathan Whitehorn 572118f387SNathan Whitehorn if (explanation == NULL) 582118f387SNathan Whitehorn explanation = ""; 592118f387SNathan Whitehorn 602118f387SNathan Whitehorn error = strtol(errstr, &errmsg, 0); 612118f387SNathan Whitehorn if (errmsg != errstr) { 622118f387SNathan Whitehorn while (errmsg[0] == ' ') 632118f387SNathan Whitehorn errmsg++; 642118f387SNathan Whitehorn if (errmsg[0] != '\0') 652118f387SNathan Whitehorn sprintf(message, "%s%s. %s", explanation, 662118f387SNathan Whitehorn strerror(error), errmsg); 672118f387SNathan Whitehorn else 682118f387SNathan Whitehorn sprintf(message, "%s%s", explanation, strerror(error)); 692118f387SNathan Whitehorn } else { 702118f387SNathan Whitehorn sprintf(message, "%s%s", explanation, errmsg); 712118f387SNathan Whitehorn } 722118f387SNathan Whitehorn 7350e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 7450e24496SAlfonso S. Siciliano conf.title = title; 7550e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, message, 0, 0); 762118f387SNathan Whitehorn } 772118f387SNathan Whitehorn 78c67f41d0SNathan Whitehorn static int 79c67f41d0SNathan Whitehorn scheme_supports_labels(const char *scheme) 80c67f41d0SNathan Whitehorn { 81c67f41d0SNathan Whitehorn if (strcmp(scheme, "APM") == 0) 82c67f41d0SNathan Whitehorn return (1); 83c67f41d0SNathan Whitehorn if (strcmp(scheme, "GPT") == 0) 84c67f41d0SNathan Whitehorn return (1); 85c67f41d0SNathan Whitehorn 86c67f41d0SNathan Whitehorn return (0); 87c67f41d0SNathan Whitehorn } 88c67f41d0SNathan Whitehorn 89*ae2fc74fSJohn Baldwin static char * 90*ae2fc74fSJohn Baldwin newfs_command(const char *fstype, int use_default) 9150de5d07SNathan Whitehorn { 9250e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 93*ae2fc74fSJohn Baldwin FILE *fp; 94*ae2fc74fSJohn Baldwin char *buf; 95*ae2fc74fSJohn Baldwin size_t len; 9650e24496SAlfonso S. Siciliano 9750e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 98*ae2fc74fSJohn Baldwin fp = open_memstream(&buf, &len); 9950e24496SAlfonso S. Siciliano 10050de5d07SNathan Whitehorn if (strcmp(fstype, "freebsd-ufs") == 0) { 10150de5d07SNathan Whitehorn int i; 10250e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 10350e24496SAlfonso S. Siciliano {"", false, 0, "UFS1", "UFS Version 1", 10450de5d07SNathan Whitehorn "Use version 1 of the UFS file system instead " 10550e24496SAlfonso S. Siciliano "of version 2 (not recommended)"}, 10650e24496SAlfonso S. Siciliano {"", true, 0, "SU", "Softupdates", 10750e24496SAlfonso S. Siciliano "Enable softupdates (default)"}, 10850e24496SAlfonso S. Siciliano {"", true, 0, "SUJ", "Softupdates journaling", 1094a8b3e41SEd Maste "Enable file system journaling (default - " 11050e24496SAlfonso S. Siciliano "turn off for SSDs)"}, 11150e24496SAlfonso S. Siciliano {"", false, 0, "TRIM", "Enable SSD TRIM support", 11250e24496SAlfonso S. Siciliano "Enable TRIM support, useful on solid-state " 11350e24496SAlfonso S. Siciliano "drives" }, 11450de5d07SNathan Whitehorn }; 11550de5d07SNathan Whitehorn 11650de5d07SNathan Whitehorn if (!use_default) { 11750de5d07SNathan Whitehorn int choice; 11850e24496SAlfonso S. Siciliano conf.title = "UFS Options"; 11950e24496SAlfonso S. Siciliano choice = bsddialog_checklist(&conf, "", 0, 0, 0, 12050e24496SAlfonso S. Siciliano nitems(items), items, NULL); 12150e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 122*ae2fc74fSJohn Baldwin goto out; 12350de5d07SNathan Whitehorn } 12450de5d07SNathan Whitehorn 125*ae2fc74fSJohn Baldwin fputs("newfs ", fp); 12663128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 12750e24496SAlfonso S. Siciliano if (items[i].on == false) 12850de5d07SNathan Whitehorn continue; 12950de5d07SNathan Whitehorn if (strcmp(items[i].name, "UFS1") == 0) 130*ae2fc74fSJohn Baldwin fputs("-O1 ", fp); 13150de5d07SNathan Whitehorn else if (strcmp(items[i].name, "SU") == 0) 132*ae2fc74fSJohn Baldwin fputs("-U ", fp); 13350de5d07SNathan Whitehorn else if (strcmp(items[i].name, "SUJ") == 0) 134*ae2fc74fSJohn Baldwin fputs("-j ", fp); 13550de5d07SNathan Whitehorn else if (strcmp(items[i].name, "TRIM") == 0) 136*ae2fc74fSJohn Baldwin fputs("-t ", fp); 13750de5d07SNathan Whitehorn } 1386e15678aSNathan Whitehorn } else if (strcmp(fstype, "freebsd-zfs") == 0) { 1396e15678aSNathan Whitehorn int i; 14050e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 14150e24496SAlfonso S. Siciliano {"", 0, true, "fletcher4", "checksum algorithm: fletcher4", 1426e15678aSNathan Whitehorn "Use fletcher4 for data integrity checking. " 14350e24496SAlfonso S. Siciliano "(default)"}, 14450e24496SAlfonso S. Siciliano {"", 0, false, "fletcher2", "checksum algorithm: fletcher2", 1456e15678aSNathan Whitehorn "Use fletcher2 for data integrity checking. " 14650e24496SAlfonso S. Siciliano "(not recommended)"}, 14750e24496SAlfonso S. Siciliano {"", 0, false, "sha256", "checksum algorithm: sha256", 1486e15678aSNathan Whitehorn "Use sha256 for data integrity checking. " 14950e24496SAlfonso S. Siciliano "(not recommended)"}, 15050e24496SAlfonso S. Siciliano {"", 0, false, "atime", "Update atimes for files", 15150e24496SAlfonso S. Siciliano "Disable atime update"}, 1526e15678aSNathan Whitehorn }; 1536e15678aSNathan Whitehorn 1546e15678aSNathan Whitehorn if (!use_default) { 1556e15678aSNathan Whitehorn int choice; 15650e24496SAlfonso S. Siciliano conf.title = "ZFS Options"; 15750e24496SAlfonso S. Siciliano choice = bsddialog_checklist(&conf, "", 0, 0, 0, 15850e24496SAlfonso S. Siciliano nitems(items), items, NULL); 15950e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 160*ae2fc74fSJohn Baldwin goto out; 1616e15678aSNathan Whitehorn } 1626e15678aSNathan Whitehorn 163*ae2fc74fSJohn Baldwin fputs("zpool create -f -m none ", fp); 1646e15678aSNathan Whitehorn if (getenv("BSDINSTALL_TMPBOOT") != NULL) { 1656e15678aSNathan Whitehorn char zfsboot_path[MAXPATHLEN]; 166*ae2fc74fSJohn Baldwin 1676c546e77SConrad Meyer snprintf(zfsboot_path, sizeof(zfsboot_path), "%s/zfs", 1686e15678aSNathan Whitehorn getenv("BSDINSTALL_TMPBOOT")); 1696e15678aSNathan Whitehorn mkdir(zfsboot_path, S_IRWXU | S_IRGRP | S_IXGRP | 1706e15678aSNathan Whitehorn S_IROTH | S_IXOTH); 171*ae2fc74fSJohn Baldwin fprintf(fp, " -o cachefile=%s/zpool.cache ", 172*ae2fc74fSJohn Baldwin zfsboot_path); 1736e15678aSNathan Whitehorn } 17463128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 17550e24496SAlfonso S. Siciliano if (items[i].on == false) 1766e15678aSNathan Whitehorn continue; 1776e15678aSNathan Whitehorn if (strcmp(items[i].name, "fletcher4") == 0) 178*ae2fc74fSJohn Baldwin fputs("-O checksum=fletcher4 ", fp); 1796e15678aSNathan Whitehorn else if (strcmp(items[i].name, "fletcher2") == 0) 180*ae2fc74fSJohn Baldwin fputs("-O checksum=fletcher2 ", fp); 1816e15678aSNathan Whitehorn else if (strcmp(items[i].name, "sha256") == 0) 182*ae2fc74fSJohn Baldwin fputs("-O checksum=sha256 ", fp); 1836e15678aSNathan Whitehorn else if (strcmp(items[i].name, "atime") == 0) 184*ae2fc74fSJohn Baldwin fputs("-O atime=off ", fp); 1856e15678aSNathan Whitehorn } 1869f7602f0SNathan Whitehorn } else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0 || 1879f7602f0SNathan Whitehorn strcmp(fstype, "ms-basic-data") == 0) { 18850de5d07SNathan Whitehorn int i; 18950e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 19050e24496SAlfonso S. Siciliano {"", 0, true, "FAT32", "FAT Type 32", 19150e24496SAlfonso S. Siciliano "Create a FAT32 filesystem (default)"}, 19250e24496SAlfonso S. Siciliano {"", 0, false, "FAT16", "FAT Type 16", 19350e24496SAlfonso S. Siciliano "Create a FAT16 filesystem"}, 19450e24496SAlfonso S. Siciliano {"", 0, false, "FAT12", "FAT Type 12", 19550e24496SAlfonso S. Siciliano "Create a FAT12 filesystem"}, 19650de5d07SNathan Whitehorn }; 19750de5d07SNathan Whitehorn 19850de5d07SNathan Whitehorn if (!use_default) { 19950de5d07SNathan Whitehorn int choice; 20050e24496SAlfonso S. Siciliano conf.title = "FAT Options"; 20150e24496SAlfonso S. Siciliano choice = bsddialog_radiolist(&conf, "", 0, 0, 0, 20250e24496SAlfonso S. Siciliano nitems(items), items, NULL); 20350e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 204*ae2fc74fSJohn Baldwin goto out; 20550de5d07SNathan Whitehorn } 20650de5d07SNathan Whitehorn 207*ae2fc74fSJohn Baldwin fputs("newfs_msdos ", fp); 20863128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 20950e24496SAlfonso S. Siciliano if (items[i].on == false) 21050de5d07SNathan Whitehorn continue; 211db8b5613SRebecca Cran if (strcmp(items[i].name, "FAT32") == 0) 212*ae2fc74fSJohn Baldwin fputs("-F 32 -c 1", fp); 213db8b5613SRebecca Cran else if (strcmp(items[i].name, "FAT16") == 0) 214*ae2fc74fSJohn Baldwin fputs("-F 16 ", fp); 215ae2e7abfSNathan Whitehorn else if (strcmp(items[i].name, "FAT12") == 0) 216*ae2fc74fSJohn Baldwin fputs("-F 12 ", fp); 21750de5d07SNathan Whitehorn } 21850de5d07SNathan Whitehorn } else { 21950e24496SAlfonso S. Siciliano if (!use_default) { 22050e24496SAlfonso S. Siciliano conf.title = "Error"; 22150e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "No configurable options exist " 22250e24496SAlfonso S. Siciliano "for this filesystem.", 0, 0); 22350e24496SAlfonso S. Siciliano } 22450de5d07SNathan Whitehorn } 225*ae2fc74fSJohn Baldwin 226*ae2fc74fSJohn Baldwin out: 227*ae2fc74fSJohn Baldwin fclose(fp); 228*ae2fc74fSJohn Baldwin return (buf); 22950de5d07SNathan Whitehorn } 23050de5d07SNathan Whitehorn 2317059fa6fSAllan Jude const char * 2327059fa6fSAllan Jude choose_part_type(const char *def_scheme) 2332118f387SNathan Whitehorn { 23450e24496SAlfonso S. Siciliano int button, choice, i; 2357059fa6fSAllan Jude const char *scheme = NULL; 23650e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 2372118f387SNathan Whitehorn 23850e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 23950e24496SAlfonso S. Siciliano {"", false, 0, "APM", "Apple Partition Map", 24050e24496SAlfonso S. Siciliano "Bootable on PowerPC Apple Hardware" }, 24150e24496SAlfonso S. Siciliano {"", false, 0, "BSD", "BSD Labels", 24250e24496SAlfonso S. Siciliano "Bootable on most x86 systems" }, 24350e24496SAlfonso S. Siciliano {"", false, 0, "GPT", "GUID Partition Table", 24450e24496SAlfonso S. Siciliano "Bootable on most x86 systems and EFI aware ARM64" }, 24550e24496SAlfonso S. Siciliano {"", false, 0, "MBR", "DOS Partitions", 24650e24496SAlfonso S. Siciliano "Bootable on most x86 systems" }, 2472118f387SNathan Whitehorn }; 2482118f387SNathan Whitehorn 24950e24496SAlfonso S. Siciliano for (i = 0; i < (int)nitems(items); i++) 25050e24496SAlfonso S. Siciliano if (strcmp(items[i].name, def_scheme) == 0) 25150e24496SAlfonso S. Siciliano choice = i; 2522118f387SNathan Whitehorn 25350e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 25450e24496SAlfonso S. Siciliano 25550e24496SAlfonso S. Siciliano parttypemenu: 25650e24496SAlfonso S. Siciliano conf.title = "Partition Scheme"; 25750e24496SAlfonso S. Siciliano button = bsddialog_menu(&conf, 25850e24496SAlfonso S. Siciliano "Select a partition scheme for this volume:", 0, 0, 0, 25950e24496SAlfonso S. Siciliano nitems(items), items, &choice); 26050e24496SAlfonso S. Siciliano 26150e24496SAlfonso S. Siciliano if (button == BSDDIALOG_CANCEL) 2627059fa6fSAllan Jude return NULL; 2632118f387SNathan Whitehorn 2642118f387SNathan Whitehorn if (!is_scheme_bootable(items[choice].name)) { 2652118f387SNathan Whitehorn char message[512]; 2662118f387SNathan Whitehorn sprintf(message, "This partition scheme (%s) is not " 2672118f387SNathan Whitehorn "bootable on this platform. Are you sure you want " 2682118f387SNathan Whitehorn "to proceed?", items[choice].name); 26950e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 27050e24496SAlfonso S. Siciliano conf.title = "Warning"; 27150e24496SAlfonso S. Siciliano button = bsddialog_yesno(&conf, message, 0, 0); 27250e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 27350e24496SAlfonso S. Siciliano if (button == BSDDIALOG_NO) 2747059fa6fSAllan Jude goto parttypemenu; 2752118f387SNathan Whitehorn } 2762118f387SNathan Whitehorn 2772118f387SNathan Whitehorn scheme = items[choice].name; 2787059fa6fSAllan Jude 2797059fa6fSAllan Jude return scheme; 2807059fa6fSAllan Jude } 2817059fa6fSAllan Jude 2827059fa6fSAllan Jude int 2837059fa6fSAllan Jude gpart_partition(const char *lg_name, const char *scheme) 2847059fa6fSAllan Jude { 28550e24496SAlfonso S. Siciliano int button; 2867059fa6fSAllan Jude struct gctl_req *r; 2877059fa6fSAllan Jude const char *errstr; 28850e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 28950e24496SAlfonso S. Siciliano 29050e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 2917059fa6fSAllan Jude 2927059fa6fSAllan Jude schememenu: 2937059fa6fSAllan Jude if (scheme == NULL) { 2947059fa6fSAllan Jude scheme = choose_part_type(default_scheme()); 2957059fa6fSAllan Jude 2967059fa6fSAllan Jude if (scheme == NULL) 2977059fa6fSAllan Jude return (-1); 2987059fa6fSAllan Jude 2997059fa6fSAllan Jude if (!is_scheme_bootable(scheme)) { 3007059fa6fSAllan Jude char message[512]; 3017059fa6fSAllan Jude sprintf(message, "This partition scheme (%s) is not " 3027059fa6fSAllan Jude "bootable on this platform. Are you sure you want " 3037059fa6fSAllan Jude "to proceed?", scheme); 30450e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 30550e24496SAlfonso S. Siciliano conf.title = "Warning"; 30650e24496SAlfonso S. Siciliano button = bsddialog_yesno(&conf, message, 0, 0); 30750e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 30850e24496SAlfonso S. Siciliano if (button == BSDDIALOG_NO) { 3097059fa6fSAllan Jude /* Reset scheme so user can choose another */ 3107059fa6fSAllan Jude scheme = NULL; 3117059fa6fSAllan Jude goto schememenu; 3127059fa6fSAllan Jude } 3137059fa6fSAllan Jude } 3142118f387SNathan Whitehorn } 3152118f387SNathan Whitehorn 3162118f387SNathan Whitehorn r = gctl_get_handle(); 3172118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 3182118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_name); 3192118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 3202118f387SNathan Whitehorn gctl_ro_param(r, "scheme", -1, scheme); 3212118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "create"); 3222118f387SNathan Whitehorn 3232118f387SNathan Whitehorn errstr = gctl_issue(r); 3242118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 3252118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 3262118f387SNathan Whitehorn gctl_free(r); 3272118f387SNathan Whitehorn scheme = NULL; 3282118f387SNathan Whitehorn goto schememenu; 3292118f387SNathan Whitehorn } 3302118f387SNathan Whitehorn gctl_free(r); 3312118f387SNathan Whitehorn 3322118f387SNathan Whitehorn if (bootcode_path(scheme) != NULL) 3332118f387SNathan Whitehorn get_part_metadata(lg_name, 1)->bootcode = 1; 3342118f387SNathan Whitehorn return (0); 3352118f387SNathan Whitehorn } 3362118f387SNathan Whitehorn 3372118f387SNathan Whitehorn static void 3382118f387SNathan Whitehorn gpart_activate(struct gprovider *pp) 3392118f387SNathan Whitehorn { 3402118f387SNathan Whitehorn struct gconfig *gc; 3412118f387SNathan Whitehorn struct gctl_req *r; 3422118f387SNathan Whitehorn const char *errstr, *scheme; 3432118f387SNathan Whitehorn const char *attribute = NULL; 3442118f387SNathan Whitehorn intmax_t idx; 3452118f387SNathan Whitehorn 3462118f387SNathan Whitehorn /* 3472118f387SNathan Whitehorn * Some partition schemes need this partition to be marked 'active' 3482118f387SNathan Whitehorn * for it to be bootable. 3492118f387SNathan Whitehorn */ 3502118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { 3512118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 3522118f387SNathan Whitehorn scheme = gc->lg_val; 3532118f387SNathan Whitehorn break; 3542118f387SNathan Whitehorn } 3552118f387SNathan Whitehorn } 3562118f387SNathan Whitehorn 3572b375b4eSYoshihiro Takahashi if (strcmp(scheme, "MBR") == 0 || strcmp(scheme, "EBR") == 0) 3582118f387SNathan Whitehorn attribute = "active"; 3592118f387SNathan Whitehorn else 3602118f387SNathan Whitehorn return; 3612118f387SNathan Whitehorn 3622118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 3632118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 3642118f387SNathan Whitehorn idx = atoi(gc->lg_val); 3652118f387SNathan Whitehorn break; 3662118f387SNathan Whitehorn } 3672118f387SNathan Whitehorn } 3682118f387SNathan Whitehorn 3692118f387SNathan Whitehorn r = gctl_get_handle(); 3702118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 3712118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); 3722118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "set"); 3732118f387SNathan Whitehorn gctl_ro_param(r, "attrib", -1, attribute); 3742118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 3752118f387SNathan Whitehorn 3762118f387SNathan Whitehorn errstr = gctl_issue(r); 3772118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 3782118f387SNathan Whitehorn gpart_show_error("Error", "Error marking partition active:", 3792118f387SNathan Whitehorn errstr); 3802118f387SNathan Whitehorn gctl_free(r); 3812118f387SNathan Whitehorn } 3822118f387SNathan Whitehorn 3837059fa6fSAllan Jude void 3847059fa6fSAllan Jude gpart_set_root(const char *lg_name, const char *attribute) 3857059fa6fSAllan Jude { 3867059fa6fSAllan Jude struct gctl_req *r; 3877059fa6fSAllan Jude const char *errstr; 3887059fa6fSAllan Jude 3897059fa6fSAllan Jude r = gctl_get_handle(); 3907059fa6fSAllan Jude gctl_ro_param(r, "class", -1, "PART"); 3917059fa6fSAllan Jude gctl_ro_param(r, "arg0", -1, lg_name); 3927059fa6fSAllan Jude gctl_ro_param(r, "flags", -1, "C"); 3937059fa6fSAllan Jude gctl_ro_param(r, "verb", -1, "set"); 3947059fa6fSAllan Jude gctl_ro_param(r, "attrib", -1, attribute); 3957059fa6fSAllan Jude 3967059fa6fSAllan Jude errstr = gctl_issue(r); 3977059fa6fSAllan Jude if (errstr != NULL && errstr[0] != '\0') 3987059fa6fSAllan Jude gpart_show_error("Error", "Error setting parameter on disk:", 3997059fa6fSAllan Jude errstr); 4007059fa6fSAllan Jude gctl_free(r); 4017059fa6fSAllan Jude } 4027059fa6fSAllan Jude 4032118f387SNathan Whitehorn static void 4042118f387SNathan Whitehorn gpart_bootcode(struct ggeom *gp) 4052118f387SNathan Whitehorn { 4062118f387SNathan Whitehorn const char *bootcode; 4072118f387SNathan Whitehorn struct gconfig *gc; 4082118f387SNathan Whitehorn struct gctl_req *r; 4092118f387SNathan Whitehorn const char *errstr, *scheme; 4102118f387SNathan Whitehorn uint8_t *boot; 4112118f387SNathan Whitehorn size_t bootsize, bytes; 4122118f387SNathan Whitehorn int bootfd; 41350e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 4142118f387SNathan Whitehorn 4152118f387SNathan Whitehorn /* 4162118f387SNathan Whitehorn * Write default bootcode to the newly partitioned disk, if that 4172118f387SNathan Whitehorn * applies on this platform. 4182118f387SNathan Whitehorn */ 4192118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 4202118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 4212118f387SNathan Whitehorn scheme = gc->lg_val; 4222118f387SNathan Whitehorn break; 4232118f387SNathan Whitehorn } 4242118f387SNathan Whitehorn } 4252118f387SNathan Whitehorn 4262118f387SNathan Whitehorn bootcode = bootcode_path(scheme); 4272118f387SNathan Whitehorn if (bootcode == NULL) 4282118f387SNathan Whitehorn return; 4292118f387SNathan Whitehorn 4302118f387SNathan Whitehorn bootfd = open(bootcode, O_RDONLY); 431c725e3efSKevin Lo if (bootfd < 0) { 43250e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 43350e24496SAlfonso S. Siciliano conf.title = "Bootcode Error"; 43450e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, strerror(errno), 0, 0); 4352118f387SNathan Whitehorn return; 4362118f387SNathan Whitehorn } 4372118f387SNathan Whitehorn 4382118f387SNathan Whitehorn bootsize = lseek(bootfd, 0, SEEK_END); 4392118f387SNathan Whitehorn boot = malloc(bootsize); 4402118f387SNathan Whitehorn lseek(bootfd, 0, SEEK_SET); 4412118f387SNathan Whitehorn bytes = 0; 4422118f387SNathan Whitehorn while (bytes < bootsize) 4432118f387SNathan Whitehorn bytes += read(bootfd, boot + bytes, bootsize - bytes); 4442118f387SNathan Whitehorn close(bootfd); 4452118f387SNathan Whitehorn 4462118f387SNathan Whitehorn r = gctl_get_handle(); 4472118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 4482118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 4492118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "bootcode"); 4502118f387SNathan Whitehorn gctl_ro_param(r, "bootcode", bootsize, boot); 4512118f387SNathan Whitehorn 4522118f387SNathan Whitehorn errstr = gctl_issue(r); 4532118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 4542118f387SNathan Whitehorn gpart_show_error("Bootcode Error", NULL, errstr); 4552118f387SNathan Whitehorn gctl_free(r); 4562118f387SNathan Whitehorn free(boot); 4572118f387SNathan Whitehorn } 4582118f387SNathan Whitehorn 4592118f387SNathan Whitehorn static void 4606e15678aSNathan Whitehorn gpart_partcode(struct gprovider *pp, const char *fstype) 4612118f387SNathan Whitehorn { 4622118f387SNathan Whitehorn struct gconfig *gc; 4632118f387SNathan Whitehorn const char *scheme; 4642118f387SNathan Whitehorn const char *indexstr; 4652118f387SNathan Whitehorn char message[255], command[255]; 46650e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 4672118f387SNathan Whitehorn 4682118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { 4692118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 4702118f387SNathan Whitehorn scheme = gc->lg_val; 4712118f387SNathan Whitehorn break; 4722118f387SNathan Whitehorn } 4732118f387SNathan Whitehorn } 4742118f387SNathan Whitehorn 4752118f387SNathan Whitehorn /* Make sure this partition scheme needs partcode on this platform */ 4766e15678aSNathan Whitehorn if (partcode_path(scheme, fstype) == NULL) 4772118f387SNathan Whitehorn return; 4782118f387SNathan Whitehorn 4792118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 4802118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 4812118f387SNathan Whitehorn indexstr = gc->lg_val; 4822118f387SNathan Whitehorn break; 4832118f387SNathan Whitehorn } 4842118f387SNathan Whitehorn } 4852118f387SNathan Whitehorn 4862118f387SNathan Whitehorn /* Shell out to gpart for partcode for now */ 4872118f387SNathan Whitehorn sprintf(command, "gpart bootcode -p %s -i %s %s", 4886e15678aSNathan Whitehorn partcode_path(scheme, fstype), indexstr, pp->lg_geom->lg_name); 4892118f387SNathan Whitehorn if (system(command) != 0) { 4902118f387SNathan Whitehorn sprintf(message, "Error installing partcode on partition %s", 4912118f387SNathan Whitehorn pp->lg_name); 49250e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 49350e24496SAlfonso S. Siciliano conf.title = "Error"; 49450e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, message, 0, 0); 4952118f387SNathan Whitehorn } 4962118f387SNathan Whitehorn } 4972118f387SNathan Whitehorn 4982118f387SNathan Whitehorn void 499f36a5e0fSNathan Whitehorn gpart_destroy(struct ggeom *lg_geom) 5002118f387SNathan Whitehorn { 5012118f387SNathan Whitehorn struct gctl_req *r; 502f36a5e0fSNathan Whitehorn struct gprovider *pp; 5032118f387SNathan Whitehorn const char *errstr; 504f36a5e0fSNathan Whitehorn int force = 1; 5052118f387SNathan Whitehorn 506f36a5e0fSNathan Whitehorn /* Delete all child metadata */ 5072118f387SNathan Whitehorn LIST_FOREACH(pp, &lg_geom->lg_provider, lg_provider) 5082118f387SNathan Whitehorn gpart_delete(pp); 5092118f387SNathan Whitehorn 510f36a5e0fSNathan Whitehorn /* Revert any local changes to get this geom into a pristine state */ 511f36a5e0fSNathan Whitehorn r = gctl_get_handle(); 512f36a5e0fSNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 513f36a5e0fSNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); 514f36a5e0fSNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 515f36a5e0fSNathan Whitehorn gctl_issue(r); /* Ignore errors -- these are non-fatal */ 516f36a5e0fSNathan Whitehorn gctl_free(r); 517f36a5e0fSNathan Whitehorn 5182118f387SNathan Whitehorn /* Now destroy the geom itself */ 5192118f387SNathan Whitehorn r = gctl_get_handle(); 5202118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 5212118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); 5222118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 523f36a5e0fSNathan Whitehorn gctl_ro_param(r, "force", sizeof(force), &force); 5242118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "destroy"); 5252118f387SNathan Whitehorn errstr = gctl_issue(r); 526987415b1SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 527987415b1SNathan Whitehorn /* 528987415b1SNathan Whitehorn * Check if we reverted away the existence of the geom 529987415b1SNathan Whitehorn * altogether. Show all other errors to the user. 530987415b1SNathan Whitehorn */ 531987415b1SNathan Whitehorn if (strtol(errstr, NULL, 0) != EINVAL) 5322118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 533987415b1SNathan Whitehorn } 5342118f387SNathan Whitehorn gctl_free(r); 5352118f387SNathan Whitehorn 5362118f387SNathan Whitehorn /* And any metadata associated with the partition scheme itself */ 5372118f387SNathan Whitehorn delete_part_metadata(lg_geom->lg_name); 5382118f387SNathan Whitehorn } 5392118f387SNathan Whitehorn 5402118f387SNathan Whitehorn void 5412118f387SNathan Whitehorn gpart_edit(struct gprovider *pp) 5422118f387SNathan Whitehorn { 5432118f387SNathan Whitehorn struct gctl_req *r; 5442118f387SNathan Whitehorn struct gconfig *gc; 5452118f387SNathan Whitehorn struct gconsumer *cp; 5462118f387SNathan Whitehorn struct ggeom *geom; 5472118f387SNathan Whitehorn const char *errstr, *oldtype, *scheme; 5482118f387SNathan Whitehorn struct partition_metadata *md; 5492118f387SNathan Whitehorn char sizestr[32]; 550*ae2fc74fSJohn Baldwin char *newfs; 5512118f387SNathan Whitehorn intmax_t idx; 55250e24496SAlfonso S. Siciliano int hadlabel, choice, nitems; 5532118f387SNathan Whitehorn unsigned i; 55450e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 5552118f387SNathan Whitehorn 55650e24496SAlfonso S. Siciliano struct bsddialog_formitem items[] = { 55750e24496SAlfonso S. Siciliano { "Type:", 1, 1, "", 1, 12, 12, 15, NULL, 0, 55850e24496SAlfonso S. Siciliano "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, " 55950e24496SAlfonso S. Siciliano "freebsd-swap)"}, 56050e24496SAlfonso S. Siciliano { "Size:", 2, 1, "", 2, 12, 12, 15, NULL, 0, 56150e24496SAlfonso S. Siciliano "Partition size. Append K, M, G for kilobytes, " 56250e24496SAlfonso S. Siciliano "megabytes or gigabytes."}, 56350e24496SAlfonso S. Siciliano { "Mountpoint:", 3, 1, "", 3, 12, 12, 15, NULL, 0, 56450e24496SAlfonso S. Siciliano "Path at which to mount this partition (leave blank " 56550e24496SAlfonso S. Siciliano "for swap, set to / for root filesystem)"}, 56650e24496SAlfonso S. Siciliano { "Label:", 4, 1, "", 4, 12, 12, 15, NULL, 0, 56750e24496SAlfonso S. Siciliano "Partition name. Not all partition schemes support this."}, 5682118f387SNathan Whitehorn }; 5692118f387SNathan Whitehorn 57050e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 57150e24496SAlfonso S. Siciliano 5722118f387SNathan Whitehorn /* 5732118f387SNathan Whitehorn * Find the PART geom we are manipulating. This may be a consumer of 5742118f387SNathan Whitehorn * this provider, or its parent. Check the consumer case first. 5752118f387SNathan Whitehorn */ 5762118f387SNathan Whitehorn geom = NULL; 5772118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 5782118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 579f36a5e0fSNathan Whitehorn /* Check for zombie geoms, treating them as blank */ 580f36a5e0fSNathan Whitehorn scheme = NULL; 581f36a5e0fSNathan Whitehorn LIST_FOREACH(gc, &cp->lg_geom->lg_config, lg_config) { 582f36a5e0fSNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 583f36a5e0fSNathan Whitehorn scheme = gc->lg_val; 584f36a5e0fSNathan Whitehorn break; 585f36a5e0fSNathan Whitehorn } 586f36a5e0fSNathan Whitehorn } 587f36a5e0fSNathan Whitehorn if (scheme == NULL || strcmp(scheme, "(none)") == 0) { 588f36a5e0fSNathan Whitehorn gpart_partition(cp->lg_geom->lg_name, NULL); 5892118f387SNathan Whitehorn return; 590f36a5e0fSNathan Whitehorn } 5912118f387SNathan Whitehorn 592987415b1SNathan Whitehorn /* If this is a nested partition, edit as usual */ 593987415b1SNathan Whitehorn if (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 594987415b1SNathan Whitehorn break; 595987415b1SNathan Whitehorn 5962118f387SNathan Whitehorn /* Destroy the geom and all sub-partitions */ 597f36a5e0fSNathan Whitehorn gpart_destroy(cp->lg_geom); 5982118f387SNathan Whitehorn 5992118f387SNathan Whitehorn /* Now re-partition and return */ 6002118f387SNathan Whitehorn gpart_partition(cp->lg_geom->lg_name, NULL); 6012118f387SNathan Whitehorn return; 6022118f387SNathan Whitehorn } 6032118f387SNathan Whitehorn 6042118f387SNathan Whitehorn if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 6052118f387SNathan Whitehorn geom = pp->lg_geom; 6062118f387SNathan Whitehorn 6072118f387SNathan Whitehorn if (geom == NULL) { 6082118f387SNathan Whitehorn /* Disk not partitioned, so partition it */ 609bcc25b7eSNathan Whitehorn gpart_partition(pp->lg_name, NULL); 6102118f387SNathan Whitehorn return; 6112118f387SNathan Whitehorn } 6122118f387SNathan Whitehorn 6132118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) { 6142118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 6152118f387SNathan Whitehorn scheme = gc->lg_val; 6162118f387SNathan Whitehorn break; 6172118f387SNathan Whitehorn } 6182118f387SNathan Whitehorn } 6192118f387SNathan Whitehorn 620c67f41d0SNathan Whitehorn nitems = scheme_supports_labels(scheme) ? 4 : 3; 6212118f387SNathan Whitehorn 6222118f387SNathan Whitehorn /* Edit editable parameters of a partition */ 6232118f387SNathan Whitehorn hadlabel = 0; 6242118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 6252118f387SNathan Whitehorn if (strcmp(gc->lg_name, "type") == 0) { 6262118f387SNathan Whitehorn oldtype = gc->lg_val; 62750e24496SAlfonso S. Siciliano items[0].init = gc->lg_val; 6282118f387SNathan Whitehorn } 6292118f387SNathan Whitehorn if (strcmp(gc->lg_name, "label") == 0 && gc->lg_val != NULL) { 6302118f387SNathan Whitehorn hadlabel = 1; 63150e24496SAlfonso S. Siciliano items[3].init = gc->lg_val; 6322118f387SNathan Whitehorn } 6332118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) 6342118f387SNathan Whitehorn idx = atoi(gc->lg_val); 6352118f387SNathan Whitehorn } 6362118f387SNathan Whitehorn 6372118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 6382118f387SNathan Whitehorn if (md->name != NULL && strcmp(md->name, pp->lg_name) == 0) { 6392118f387SNathan Whitehorn if (md->fstab != NULL) 64050e24496SAlfonso S. Siciliano items[2].init = md->fstab->fs_file; 6412118f387SNathan Whitehorn break; 6422118f387SNathan Whitehorn } 6432118f387SNathan Whitehorn } 6442118f387SNathan Whitehorn 6452118f387SNathan Whitehorn humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE, 6462118f387SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 64750e24496SAlfonso S. Siciliano items[1].init = sizestr; 6482118f387SNathan Whitehorn 6492118f387SNathan Whitehorn editpart: 6507ef6e997SAlfonso S. Siciliano conf.button.always_active = true; 65150e24496SAlfonso S. Siciliano conf.title = "Edit Partition"; 65261ba55bcSBaptiste Daroussin choice = bsddialog_form(&conf, "", 0, 0, 0, nitems, items, NULL); 6537ef6e997SAlfonso S. Siciliano conf.button.always_active = false; 6542118f387SNathan Whitehorn 65550e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 656987415b1SNathan Whitehorn goto endedit; 6572118f387SNathan Whitehorn 658e24e98d0SWojciech Macek /* If this is the root partition, check that this fs is bootable */ 65950e24496SAlfonso S. Siciliano if (strcmp(items[2].value, "/") == 0 && !is_fs_bootable(scheme, 66050e24496SAlfonso S. Siciliano items[0].value)) { 661e24e98d0SWojciech Macek char message[512]; 662e24e98d0SWojciech Macek sprintf(message, "This file system (%s) is not bootable " 663e24e98d0SWojciech Macek "on this system. Are you sure you want to proceed?", 66450e24496SAlfonso S. Siciliano items[0].value); 66550e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 66650e24496SAlfonso S. Siciliano conf.title = "Warning"; 66750e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, message, 0, 0); 66850e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 66950e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 670e24e98d0SWojciech Macek goto editpart; 671e24e98d0SWojciech Macek } 672e24e98d0SWojciech Macek 6732118f387SNathan Whitehorn /* Check if the label has a / in it */ 67450e24496SAlfonso S. Siciliano if (items[3].value != NULL && strchr(items[3].value, '/') != NULL) { 67550e24496SAlfonso S. Siciliano conf.title = "Error"; 67650e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "Label contains a /, which is not an " 67750e24496SAlfonso S. Siciliano "allowed character.", 0, 0); 6782118f387SNathan Whitehorn goto editpart; 6792118f387SNathan Whitehorn } 6802118f387SNathan Whitehorn 6812118f387SNathan Whitehorn r = gctl_get_handle(); 6822118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 6832118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 6842118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 6852118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "modify"); 6862118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 68750e24496SAlfonso S. Siciliano if (items[3].value != NULL && (hadlabel || items[3].value[0] != '\0')) 68850e24496SAlfonso S. Siciliano gctl_ro_param(r, "label", -1, items[3].value); 68950e24496SAlfonso S. Siciliano gctl_ro_param(r, "type", -1, items[0].value); 6902118f387SNathan Whitehorn errstr = gctl_issue(r); 6912118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 6922118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 6932118f387SNathan Whitehorn gctl_free(r); 6942118f387SNathan Whitehorn goto editpart; 6952118f387SNathan Whitehorn } 6962118f387SNathan Whitehorn gctl_free(r); 6972118f387SNathan Whitehorn 698*ae2fc74fSJohn Baldwin newfs = newfs_command(items[0].value, 1); 69950e24496SAlfonso S. Siciliano set_default_part_metadata(pp->lg_name, scheme, items[0].value, 70050e24496SAlfonso S. Siciliano items[2].value, (strcmp(oldtype, items[0].value) != 0) ? 70150de5d07SNathan Whitehorn newfs : NULL); 702*ae2fc74fSJohn Baldwin free(newfs); 7032118f387SNathan Whitehorn 704987415b1SNathan Whitehorn endedit: 70550e24496SAlfonso S. Siciliano if (strcmp(oldtype, items[0].value) != 0 && cp != NULL) 706987415b1SNathan Whitehorn gpart_destroy(cp->lg_geom); 70750e24496SAlfonso S. Siciliano if (strcmp(oldtype, items[0].value) != 0 && strcmp(items[0].value, 708987415b1SNathan Whitehorn "freebsd") == 0) 709987415b1SNathan Whitehorn gpart_partition(pp->lg_name, "BSD"); 710987415b1SNathan Whitehorn 71163128851SMarcelo Araujo for (i = 0; i < nitems(items); i++) 71250e24496SAlfonso S. Siciliano if (items[i].value != NULL) 71350e24496SAlfonso S. Siciliano free(items[i].value); 7142118f387SNathan Whitehorn } 7152118f387SNathan Whitehorn 7162118f387SNathan Whitehorn void 7172118f387SNathan Whitehorn set_default_part_metadata(const char *name, const char *scheme, 71850de5d07SNathan Whitehorn const char *type, const char *mountpoint, const char *newfs) 7192118f387SNathan Whitehorn { 7202118f387SNathan Whitehorn struct partition_metadata *md; 7216e15678aSNathan Whitehorn char *zpool_name = NULL; 72252f39da1SNathan Whitehorn const char *default_bootmount = NULL; 7236e15678aSNathan Whitehorn int i; 7242118f387SNathan Whitehorn 7252118f387SNathan Whitehorn /* Set part metadata */ 7262118f387SNathan Whitehorn md = get_part_metadata(name, 1); 7272118f387SNathan Whitehorn 7282118f387SNathan Whitehorn if (newfs) { 7292118f387SNathan Whitehorn if (md->newfs != NULL) { 7302118f387SNathan Whitehorn free(md->newfs); 7312118f387SNathan Whitehorn md->newfs = NULL; 7322118f387SNathan Whitehorn } 7332118f387SNathan Whitehorn 73450de5d07SNathan Whitehorn if (newfs != NULL && newfs[0] != '\0') { 73550de5d07SNathan Whitehorn md->newfs = malloc(strlen(newfs) + strlen(" /dev/") + 7366e15678aSNathan Whitehorn strlen(mountpoint) + 5 + strlen(name) + 1); 7376e15678aSNathan Whitehorn if (strcmp("freebsd-zfs", type) == 0) { 7386e15678aSNathan Whitehorn zpool_name = strdup((strlen(mountpoint) == 1) ? 7396e15678aSNathan Whitehorn "root" : &mountpoint[1]); 7406e15678aSNathan Whitehorn for (i = 0; zpool_name[i] != 0; i++) 7416e15678aSNathan Whitehorn if (!isalnum(zpool_name[i])) 7426e15678aSNathan Whitehorn zpool_name[i] = '_'; 7436e15678aSNathan Whitehorn sprintf(md->newfs, "%s %s /dev/%s", newfs, 7446e15678aSNathan Whitehorn zpool_name, name); 7456e15678aSNathan Whitehorn } else { 74650de5d07SNathan Whitehorn sprintf(md->newfs, "%s /dev/%s", newfs, name); 7472118f387SNathan Whitehorn } 7482118f387SNathan Whitehorn } 7496e15678aSNathan Whitehorn } 7502118f387SNathan Whitehorn 7512118f387SNathan Whitehorn if (strcmp(type, "freebsd-swap") == 0) 7522118f387SNathan Whitehorn mountpoint = "none"; 75352f39da1SNathan Whitehorn if (strcmp(type, bootpart_type(scheme, &default_bootmount)) == 0) { 7540b7472b3SNathan Whitehorn if (default_bootmount == NULL) 7552118f387SNathan Whitehorn md->bootcode = 1; 75652f39da1SNathan Whitehorn else if (mountpoint == NULL || strlen(mountpoint) == 0) 75752f39da1SNathan Whitehorn mountpoint = default_bootmount; 75852f39da1SNathan Whitehorn } 7592118f387SNathan Whitehorn 7602118f387SNathan Whitehorn if (mountpoint == NULL || mountpoint[0] == '\0') { 7612118f387SNathan Whitehorn if (md->fstab != NULL) { 7622118f387SNathan Whitehorn free(md->fstab->fs_spec); 7632118f387SNathan Whitehorn free(md->fstab->fs_file); 7642118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 7652118f387SNathan Whitehorn free(md->fstab->fs_mntops); 7662118f387SNathan Whitehorn free(md->fstab->fs_type); 7672118f387SNathan Whitehorn free(md->fstab); 7682118f387SNathan Whitehorn md->fstab = NULL; 7692118f387SNathan Whitehorn } 7702118f387SNathan Whitehorn } else { 7712118f387SNathan Whitehorn if (md->fstab == NULL) { 7722118f387SNathan Whitehorn md->fstab = malloc(sizeof(struct fstab)); 7732118f387SNathan Whitehorn } else { 7742118f387SNathan Whitehorn free(md->fstab->fs_spec); 7752118f387SNathan Whitehorn free(md->fstab->fs_file); 7762118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 7772118f387SNathan Whitehorn free(md->fstab->fs_mntops); 7782118f387SNathan Whitehorn free(md->fstab->fs_type); 7792118f387SNathan Whitehorn } 7806e15678aSNathan Whitehorn if (strcmp("freebsd-zfs", type) == 0) { 7816e15678aSNathan Whitehorn md->fstab->fs_spec = strdup(zpool_name); 7826e15678aSNathan Whitehorn } else { 7836e15678aSNathan Whitehorn md->fstab->fs_spec = malloc(strlen(name) + 7846e15678aSNathan Whitehorn strlen("/dev/") + 1); 7852118f387SNathan Whitehorn sprintf(md->fstab->fs_spec, "/dev/%s", name); 7866e15678aSNathan Whitehorn } 7872118f387SNathan Whitehorn md->fstab->fs_file = strdup(mountpoint); 7882118f387SNathan Whitehorn /* Get VFS from text after freebsd-, if possible */ 78950de5d07SNathan Whitehorn if (strncmp("freebsd-", type, 8) == 0) 7902118f387SNathan Whitehorn md->fstab->fs_vfstype = strdup(&type[8]); 7919f7602f0SNathan Whitehorn else if (strcmp("fat32", type) == 0 || strcmp("efi", type) == 0 7929f7602f0SNathan Whitehorn || strcmp("ms-basic-data", type) == 0) 79350de5d07SNathan Whitehorn md->fstab->fs_vfstype = strdup("msdosfs"); 7942118f387SNathan Whitehorn else 7952118f387SNathan Whitehorn md->fstab->fs_vfstype = strdup(type); /* Guess */ 7962118f387SNathan Whitehorn if (strcmp(type, "freebsd-swap") == 0) { 7972118f387SNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_SW); 7982118f387SNathan Whitehorn md->fstab->fs_freq = 0; 7992118f387SNathan Whitehorn md->fstab->fs_passno = 0; 8006e15678aSNathan Whitehorn } else if (strcmp(type, "freebsd-zfs") == 0) { 8016e15678aSNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_RW); 8026e15678aSNathan Whitehorn md->fstab->fs_freq = 0; 8036e15678aSNathan Whitehorn md->fstab->fs_passno = 0; 8042118f387SNathan Whitehorn } else { 8052118f387SNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_RW); 8062118f387SNathan Whitehorn if (strcmp(mountpoint, "/") == 0) { 8072118f387SNathan Whitehorn md->fstab->fs_freq = 1; 8082118f387SNathan Whitehorn md->fstab->fs_passno = 1; 8092118f387SNathan Whitehorn } else { 8102118f387SNathan Whitehorn md->fstab->fs_freq = 2; 8112118f387SNathan Whitehorn md->fstab->fs_passno = 2; 8122118f387SNathan Whitehorn } 8132118f387SNathan Whitehorn } 8142118f387SNathan Whitehorn md->fstab->fs_mntops = strdup(md->fstab->fs_type); 8152118f387SNathan Whitehorn } 8166e15678aSNathan Whitehorn 8176e15678aSNathan Whitehorn if (zpool_name != NULL) 8186e15678aSNathan Whitehorn free(zpool_name); 8192118f387SNathan Whitehorn } 8202118f387SNathan Whitehorn 8212118f387SNathan Whitehorn static 8222118f387SNathan Whitehorn int part_compare(const void *xa, const void *xb) 8232118f387SNathan Whitehorn { 8242118f387SNathan Whitehorn struct gprovider **a = (struct gprovider **)xa; 8252118f387SNathan Whitehorn struct gprovider **b = (struct gprovider **)xb; 8262118f387SNathan Whitehorn intmax_t astart, bstart; 8272118f387SNathan Whitehorn struct gconfig *gc; 8282118f387SNathan Whitehorn 8292118f387SNathan Whitehorn astart = bstart = 0; 8302118f387SNathan Whitehorn LIST_FOREACH(gc, &(*a)->lg_config, lg_config) 8312118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) { 8322118f387SNathan Whitehorn astart = strtoimax(gc->lg_val, NULL, 0); 8332118f387SNathan Whitehorn break; 8342118f387SNathan Whitehorn } 8352118f387SNathan Whitehorn LIST_FOREACH(gc, &(*b)->lg_config, lg_config) 8362118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) { 8372118f387SNathan Whitehorn bstart = strtoimax(gc->lg_val, NULL, 0); 8382118f387SNathan Whitehorn break; 8392118f387SNathan Whitehorn } 8402118f387SNathan Whitehorn 8412118f387SNathan Whitehorn if (astart < bstart) 8422118f387SNathan Whitehorn return -1; 8432118f387SNathan Whitehorn else if (astart > bstart) 8442118f387SNathan Whitehorn return 1; 8452118f387SNathan Whitehorn else 8462118f387SNathan Whitehorn return 0; 8472118f387SNathan Whitehorn } 8482118f387SNathan Whitehorn 8492118f387SNathan Whitehorn intmax_t 8502118f387SNathan Whitehorn gpart_max_free(struct ggeom *geom, intmax_t *npartstart) 8512118f387SNathan Whitehorn { 8522118f387SNathan Whitehorn struct gconfig *gc; 8532118f387SNathan Whitehorn struct gprovider *pp, **providers; 85447ead00dSDag-Erling Smørgrav intmax_t sectorsize, stripesize, offset; 8552118f387SNathan Whitehorn intmax_t lastend; 8562118f387SNathan Whitehorn intmax_t start, end; 8572118f387SNathan Whitehorn intmax_t maxsize, maxstart; 8582118f387SNathan Whitehorn intmax_t partstart, partend; 8592118f387SNathan Whitehorn int i, nparts; 8602118f387SNathan Whitehorn 8612118f387SNathan Whitehorn /* Now get the maximum free size and free start */ 8622118f387SNathan Whitehorn start = end = 0; 8632118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) { 8642118f387SNathan Whitehorn if (strcmp(gc->lg_name, "first") == 0) 8652118f387SNathan Whitehorn start = strtoimax(gc->lg_val, NULL, 0); 8662118f387SNathan Whitehorn if (strcmp(gc->lg_name, "last") == 0) 8672118f387SNathan Whitehorn end = strtoimax(gc->lg_val, NULL, 0); 8682118f387SNathan Whitehorn } 8692118f387SNathan Whitehorn 8702118f387SNathan Whitehorn i = nparts = 0; 8712118f387SNathan Whitehorn LIST_FOREACH(pp, &geom->lg_provider, lg_provider) 8722118f387SNathan Whitehorn nparts++; 8732118f387SNathan Whitehorn providers = calloc(nparts, sizeof(providers[0])); 8742118f387SNathan Whitehorn LIST_FOREACH(pp, &geom->lg_provider, lg_provider) 8752118f387SNathan Whitehorn providers[i++] = pp; 8762118f387SNathan Whitehorn qsort(providers, nparts, sizeof(providers[0]), part_compare); 8772118f387SNathan Whitehorn 8782118f387SNathan Whitehorn lastend = start - 1; 8792118f387SNathan Whitehorn maxsize = 0; 8802118f387SNathan Whitehorn for (i = 0; i < nparts; i++) { 8812118f387SNathan Whitehorn pp = providers[i]; 8822118f387SNathan Whitehorn 8832118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 8842118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) 8852118f387SNathan Whitehorn partstart = strtoimax(gc->lg_val, NULL, 0); 8862118f387SNathan Whitehorn if (strcmp(gc->lg_name, "end") == 0) 8872118f387SNathan Whitehorn partend = strtoimax(gc->lg_val, NULL, 0); 8882118f387SNathan Whitehorn } 8892118f387SNathan Whitehorn 8902118f387SNathan Whitehorn if (partstart - lastend > maxsize) { 8912118f387SNathan Whitehorn maxsize = partstart - lastend - 1; 8922118f387SNathan Whitehorn maxstart = lastend + 1; 8932118f387SNathan Whitehorn } 8942118f387SNathan Whitehorn 8952118f387SNathan Whitehorn lastend = partend; 8962118f387SNathan Whitehorn } 8972118f387SNathan Whitehorn 8982118f387SNathan Whitehorn if (end - lastend > maxsize) { 8998c7de243SNathan Whitehorn maxsize = end - lastend; 9002118f387SNathan Whitehorn maxstart = lastend + 1; 9012118f387SNathan Whitehorn } 9022118f387SNathan Whitehorn 9032118f387SNathan Whitehorn pp = LIST_FIRST(&geom->lg_consumer)->lg_provider; 9042118f387SNathan Whitehorn 90547ead00dSDag-Erling Smørgrav /* 90647ead00dSDag-Erling Smørgrav * Round the start and size of the largest available space up to 90747ead00dSDag-Erling Smørgrav * the nearest multiple of the adjusted stripe size. 90847ead00dSDag-Erling Smørgrav * 90947ead00dSDag-Erling Smørgrav * The adjusted stripe size is the least common multiple of the 91047ead00dSDag-Erling Smørgrav * actual stripe size, or the sector size if no stripe size was 91147ead00dSDag-Erling Smørgrav * reported, and 4096. The reason for this is that contemporary 91247ead00dSDag-Erling Smørgrav * disks often have 4096-byte physical sectors but report 512 91347ead00dSDag-Erling Smørgrav * bytes instead for compatibility with older / broken operating 91447ead00dSDag-Erling Smørgrav * systems and BIOSes. For the same reasons, virtualized storage 91547ead00dSDag-Erling Smørgrav * may also report a 512-byte stripe size, or none at all. 91647ead00dSDag-Erling Smørgrav */ 91747ead00dSDag-Erling Smørgrav sectorsize = pp->lg_sectorsize; 91847ead00dSDag-Erling Smørgrav if ((stripesize = pp->lg_stripesize) == 0) 91947ead00dSDag-Erling Smørgrav stripesize = sectorsize; 92047ead00dSDag-Erling Smørgrav while (stripesize % 4096 != 0) 92147ead00dSDag-Erling Smørgrav stripesize *= 2; 92247ead00dSDag-Erling Smørgrav if ((offset = maxstart * sectorsize % stripesize) != 0) { 92347ead00dSDag-Erling Smørgrav offset = (stripesize - offset) / sectorsize; 9242118f387SNathan Whitehorn maxstart += offset; 9252118f387SNathan Whitehorn maxsize -= offset; 9262118f387SNathan Whitehorn } 9272118f387SNathan Whitehorn 9282118f387SNathan Whitehorn if (npartstart != NULL) 9292118f387SNathan Whitehorn *npartstart = maxstart; 9302118f387SNathan Whitehorn 9312118f387SNathan Whitehorn return (maxsize); 9322118f387SNathan Whitehorn } 9332118f387SNathan Whitehorn 93452f39da1SNathan Whitehorn static size_t 93552f39da1SNathan Whitehorn add_boot_partition(struct ggeom *geom, struct gprovider *pp, 93652f39da1SNathan Whitehorn const char *scheme, int interactive) 93752f39da1SNathan Whitehorn { 93852f39da1SNathan Whitehorn struct gconfig *gc; 93952f39da1SNathan Whitehorn struct gprovider *ppi; 94052f39da1SNathan Whitehorn int choice; 94150e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 94252f39da1SNathan Whitehorn 94352f39da1SNathan Whitehorn /* Check for existing freebsd-boot partition */ 94452f39da1SNathan Whitehorn LIST_FOREACH(ppi, &geom->lg_provider, lg_provider) { 94552f39da1SNathan Whitehorn struct partition_metadata *md; 94652f39da1SNathan Whitehorn const char *bootmount = NULL; 94752f39da1SNathan Whitehorn 94852f39da1SNathan Whitehorn LIST_FOREACH(gc, &ppi->lg_config, lg_config) 94952f39da1SNathan Whitehorn if (strcmp(gc->lg_name, "type") == 0) 95052f39da1SNathan Whitehorn break; 95152f39da1SNathan Whitehorn if (gc == NULL) 95252f39da1SNathan Whitehorn continue; 95352f39da1SNathan Whitehorn if (strcmp(gc->lg_val, bootpart_type(scheme, &bootmount)) != 0) 95452f39da1SNathan Whitehorn continue; 95552f39da1SNathan Whitehorn 95652f39da1SNathan Whitehorn /* 95752f39da1SNathan Whitehorn * If the boot partition is not mountable and needs partcode, 95852f39da1SNathan Whitehorn * but doesn't have it, it doesn't satisfy our requirements. 95952f39da1SNathan Whitehorn */ 96052f39da1SNathan Whitehorn md = get_part_metadata(ppi->lg_name, 0); 96152f39da1SNathan Whitehorn if (bootmount == NULL && (md == NULL || !md->bootcode)) 96252f39da1SNathan Whitehorn continue; 96352f39da1SNathan Whitehorn 96452f39da1SNathan Whitehorn /* If it is mountable, but mounted somewhere else, remount */ 96552f39da1SNathan Whitehorn if (bootmount != NULL && md != NULL && md->fstab != NULL 96652f39da1SNathan Whitehorn && strlen(md->fstab->fs_file) > 0 96752f39da1SNathan Whitehorn && strcmp(md->fstab->fs_file, bootmount) != 0) 96852f39da1SNathan Whitehorn continue; 96952f39da1SNathan Whitehorn 97052f39da1SNathan Whitehorn /* If it is mountable, but mountpoint is not set, mount it */ 97152f39da1SNathan Whitehorn if (bootmount != NULL && md == NULL) 97252f39da1SNathan Whitehorn set_default_part_metadata(ppi->lg_name, scheme, 97352f39da1SNathan Whitehorn gc->lg_val, bootmount, NULL); 97452f39da1SNathan Whitehorn 97552f39da1SNathan Whitehorn /* Looks good at this point, no added data needed */ 97652f39da1SNathan Whitehorn return (0); 97752f39da1SNathan Whitehorn } 97852f39da1SNathan Whitehorn 97950e24496SAlfonso S. Siciliano if (interactive) { 98050e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 98150e24496SAlfonso S. Siciliano conf.title = "Boot Partition"; 98250e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, 98352f39da1SNathan Whitehorn "This partition scheme requires a boot partition " 98452f39da1SNathan Whitehorn "for the disk to be bootable. Would you like to " 98552f39da1SNathan Whitehorn "make one now?", 0, 0); 98650e24496SAlfonso S. Siciliano } else { 98750e24496SAlfonso S. Siciliano choice = BSDDIALOG_YES; 98850e24496SAlfonso S. Siciliano } 98952f39da1SNathan Whitehorn 99050e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_YES) { 9916134b186SNathan Whitehorn struct partition_metadata *md; 99252f39da1SNathan Whitehorn const char *bootmount = NULL; 9936134b186SNathan Whitehorn char *bootpartname = NULL; 99452f39da1SNathan Whitehorn char sizestr[7]; 99552f39da1SNathan Whitehorn 99652f39da1SNathan Whitehorn humanize_number(sizestr, 7, 99752f39da1SNathan Whitehorn bootpart_size(scheme), "B", HN_AUTOSCALE, 99852f39da1SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 99952f39da1SNathan Whitehorn 100052f39da1SNathan Whitehorn gpart_create(pp, bootpart_type(scheme, &bootmount), 10016134b186SNathan Whitehorn sizestr, bootmount, &bootpartname, 0); 10026134b186SNathan Whitehorn 10036134b186SNathan Whitehorn if (bootpartname == NULL) /* Error reported to user already */ 10046134b186SNathan Whitehorn return 0; 10056134b186SNathan Whitehorn 10066134b186SNathan Whitehorn /* If the part is not mountable, make sure newfs isn't set */ 10076134b186SNathan Whitehorn if (bootmount == NULL) { 10086134b186SNathan Whitehorn md = get_part_metadata(bootpartname, 0); 10096134b186SNathan Whitehorn if (md != NULL && md->newfs != NULL) { 10106134b186SNathan Whitehorn free(md->newfs); 10116134b186SNathan Whitehorn md->newfs = NULL; 10126134b186SNathan Whitehorn } 10136134b186SNathan Whitehorn } 10146134b186SNathan Whitehorn 10156134b186SNathan Whitehorn free(bootpartname); 101652f39da1SNathan Whitehorn 101752f39da1SNathan Whitehorn return (bootpart_size(scheme)); 101852f39da1SNathan Whitehorn } 101952f39da1SNathan Whitehorn 102052f39da1SNathan Whitehorn return (0); 102152f39da1SNathan Whitehorn } 102252f39da1SNathan Whitehorn 10232118f387SNathan Whitehorn void 102452f39da1SNathan Whitehorn gpart_create(struct gprovider *pp, const char *default_type, 102552f39da1SNathan Whitehorn const char *default_size, const char *default_mountpoint, 102652f39da1SNathan Whitehorn char **partname, int interactive) 10272118f387SNathan Whitehorn { 10282118f387SNathan Whitehorn struct gctl_req *r; 10292118f387SNathan Whitehorn struct gconfig *gc; 10302118f387SNathan Whitehorn struct gconsumer *cp; 10312118f387SNathan Whitehorn struct ggeom *geom; 10322118f387SNathan Whitehorn const char *errstr, *scheme; 10337899c6c1SNathan Whitehorn char sizestr[32], startstr[32], output[64], *newpartname; 1034*ae2fc74fSJohn Baldwin char *newfs, options_fstype[64]; 10352118f387SNathan Whitehorn intmax_t maxsize, size, sector, firstfree, stripe; 10362118f387SNathan Whitehorn uint64_t bytes; 10372118f387SNathan Whitehorn int nitems, choice, junk; 10382118f387SNathan Whitehorn unsigned i; 103950e24496SAlfonso S. Siciliano bool init_allocated; 104050e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 10412118f387SNathan Whitehorn 104250e24496SAlfonso S. Siciliano struct bsddialog_formitem items[] = { 104350e24496SAlfonso S. Siciliano {"Type:", 1, 1, "freebsd-ufs", 1, 12, 12, 15, NULL, 0, 104450e24496SAlfonso S. Siciliano "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, " 104550e24496SAlfonso S. Siciliano "freebsd-swap)"}, 104650e24496SAlfonso S. Siciliano {"Size:", 2, 1, "", 2, 12, 12, 15, NULL, 0, 104750e24496SAlfonso S. Siciliano "Partition size. Append K, M, G for kilobytes, " 104850e24496SAlfonso S. Siciliano "megabytes or gigabytes."}, 104950e24496SAlfonso S. Siciliano {"Mountpoint:", 3, 1, "", 3, 12, 12, 15, NULL, 0, 105050e24496SAlfonso S. Siciliano "Path at which to mount partition (blank for " 105150e24496SAlfonso S. Siciliano "swap, / for root filesystem)"}, 105250e24496SAlfonso S. Siciliano {"Label:", 4, 1, "", 4, 12, 12, 15, NULL, 0, 105350e24496SAlfonso S. Siciliano "Partition name. Not all partition schemes support this."}, 10542118f387SNathan Whitehorn }; 10552118f387SNathan Whitehorn 105650e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 105750e24496SAlfonso S. Siciliano 10582118f387SNathan Whitehorn if (partname != NULL) 10592118f387SNathan Whitehorn *partname = NULL; 10602118f387SNathan Whitehorn 10612118f387SNathan Whitehorn /* Record sector and stripe sizes */ 10622118f387SNathan Whitehorn sector = pp->lg_sectorsize; 10632118f387SNathan Whitehorn stripe = pp->lg_stripesize; 10642118f387SNathan Whitehorn 10652118f387SNathan Whitehorn /* 10662118f387SNathan Whitehorn * Find the PART geom we are manipulating. This may be a consumer of 10672118f387SNathan Whitehorn * this provider, or its parent. Check the consumer case first. 10682118f387SNathan Whitehorn */ 10692118f387SNathan Whitehorn geom = NULL; 10702118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 10712118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 10722118f387SNathan Whitehorn geom = cp->lg_geom; 10732118f387SNathan Whitehorn break; 10742118f387SNathan Whitehorn } 10752118f387SNathan Whitehorn 10762118f387SNathan Whitehorn if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 10772118f387SNathan Whitehorn geom = pp->lg_geom; 10782118f387SNathan Whitehorn 10792118f387SNathan Whitehorn /* Now get the partition scheme */ 10802118f387SNathan Whitehorn scheme = NULL; 10812118f387SNathan Whitehorn if (geom != NULL) { 10822118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) 10832118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) 10842118f387SNathan Whitehorn scheme = gc->lg_val; 10852118f387SNathan Whitehorn } 10862118f387SNathan Whitehorn 10872118f387SNathan Whitehorn if (geom == NULL || scheme == NULL || strcmp(scheme, "(none)") == 0) { 108850e24496SAlfonso S. Siciliano if (gpart_partition(pp->lg_name, NULL) == 0) { 108950e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, 10902118f387SNathan Whitehorn "The partition table has been successfully created." 10912118f387SNathan Whitehorn " Please press Create again to create partitions.", 109250e24496SAlfonso S. Siciliano 0, 0); 109350e24496SAlfonso S. Siciliano } 10942118f387SNathan Whitehorn 10952118f387SNathan Whitehorn return; 10962118f387SNathan Whitehorn } 10972118f387SNathan Whitehorn 10982118f387SNathan Whitehorn /* 10992118f387SNathan Whitehorn * If we still don't have a geom, either the user has 11002118f387SNathan Whitehorn * canceled partitioning or there has been an error which has already 11012118f387SNathan Whitehorn * been displayed, so bail. 11022118f387SNathan Whitehorn */ 11032118f387SNathan Whitehorn if (geom == NULL) 11042118f387SNathan Whitehorn return; 11052118f387SNathan Whitehorn 11062118f387SNathan Whitehorn maxsize = size = gpart_max_free(geom, &firstfree); 11072118f387SNathan Whitehorn if (size <= 0) { 110850e24496SAlfonso S. Siciliano conf .title = "Error"; 110950e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "No free space left on device.", 0, 0); 11102118f387SNathan Whitehorn return; 11112118f387SNathan Whitehorn } 11122118f387SNathan Whitehorn 11132118f387SNathan Whitehorn humanize_number(sizestr, 7, size*sector, "B", HN_AUTOSCALE, 11142118f387SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 111550e24496SAlfonso S. Siciliano items[1].init = sizestr; 11162118f387SNathan Whitehorn 11172118f387SNathan Whitehorn /* Special-case the MBR default type for nested partitions */ 11182b375b4eSYoshihiro Takahashi if (strcmp(scheme, "MBR") == 0) { 111950e24496SAlfonso S. Siciliano items[0].init = "freebsd"; 112050e24496SAlfonso S. Siciliano items[0].bottomdesc = "Filesystem type (e.g. freebsd, fat32)"; 1121bcc25b7eSNathan Whitehorn } 11222118f387SNathan Whitehorn 1123c67f41d0SNathan Whitehorn nitems = scheme_supports_labels(scheme) ? 4 : 3; 11242118f387SNathan Whitehorn 11252118f387SNathan Whitehorn if (default_type != NULL) 112650e24496SAlfonso S. Siciliano items[0].init = (char *)default_type; 11272118f387SNathan Whitehorn if (default_size != NULL) 112850e24496SAlfonso S. Siciliano items[1].init = (char *)default_size; 11292118f387SNathan Whitehorn if (default_mountpoint != NULL) 113050e24496SAlfonso S. Siciliano items[2].init = (char *)default_mountpoint; 11312118f387SNathan Whitehorn 113250de5d07SNathan Whitehorn /* Default options */ 113350e24496SAlfonso S. Siciliano strncpy(options_fstype, items[0].init, 113450de5d07SNathan Whitehorn sizeof(options_fstype)); 1135*ae2fc74fSJohn Baldwin newfs = newfs_command(options_fstype, 1); 113650e24496SAlfonso S. Siciliano 113750e24496SAlfonso S. Siciliano init_allocated = false; 11382118f387SNathan Whitehorn addpartform: 11392118f387SNathan Whitehorn if (interactive) { 114050e24496SAlfonso S. Siciliano conf.button.with_extra = true; 114150e24496SAlfonso S. Siciliano conf.button.extra_label = "Options"; 11427ef6e997SAlfonso S. Siciliano conf.button.always_active = true; 114350e24496SAlfonso S. Siciliano conf.title = "Add Partition"; 114461ba55bcSBaptiste Daroussin choice = bsddialog_form(&conf, "", 0, 0, 0, nitems, items, NULL); 114550e24496SAlfonso S. Siciliano conf.button.with_extra = false; 114650e24496SAlfonso S. Siciliano conf.button.extra_label = NULL; 11477ef6e997SAlfonso S. Siciliano conf.button.always_active = false; 114850de5d07SNathan Whitehorn switch (choice) { 114950e24496SAlfonso S. Siciliano case BSDDIALOG_OK: 115050de5d07SNathan Whitehorn break; 115150e24496SAlfonso S. Siciliano case BSDDIALOG_CANCEL: 11522118f387SNathan Whitehorn return; 115350e24496SAlfonso S. Siciliano case BSDDIALOG_EXTRA: /* Options */ 1154*ae2fc74fSJohn Baldwin free(newfs); 115550e24496SAlfonso S. Siciliano strncpy(options_fstype, items[0].value, 115650de5d07SNathan Whitehorn sizeof(options_fstype)); 1157*ae2fc74fSJohn Baldwin newfs = newfs_command(options_fstype, 0); 115850e24496SAlfonso S. Siciliano for (i = 0; i < nitems(items); i++) { 115950e24496SAlfonso S. Siciliano if (init_allocated) 116050e24496SAlfonso S. Siciliano free((char*)items[i].init); 116150e24496SAlfonso S. Siciliano items[i].init = items[i].value; 116250e24496SAlfonso S. Siciliano } 116350e24496SAlfonso S. Siciliano init_allocated = true; 116450de5d07SNathan Whitehorn goto addpartform; 116550de5d07SNathan Whitehorn } 11669b4c606bSAlfonso S. Siciliano } else { /* auto partitioning */ 11679b4c606bSAlfonso S. Siciliano items[0].value = strdup(items[0].init); 11689b4c606bSAlfonso S. Siciliano items[1].value = strdup(items[1].init); 11699b4c606bSAlfonso S. Siciliano items[2].value = strdup(items[2].init); 11709b4c606bSAlfonso S. Siciliano if (nitems > 3) 11719b4c606bSAlfonso S. Siciliano items[3].value = strdup(items[3].init); 117250de5d07SNathan Whitehorn } 117350de5d07SNathan Whitehorn 117450de5d07SNathan Whitehorn /* 117550de5d07SNathan Whitehorn * If the user changed the fs type after specifying options, undo 117650de5d07SNathan Whitehorn * their choices in favor of the new filesystem's defaults. 117750de5d07SNathan Whitehorn */ 117850e24496SAlfonso S. Siciliano if (strcmp(options_fstype, items[0].value) != 0) { 1179*ae2fc74fSJohn Baldwin free(newfs); 118050e24496SAlfonso S. Siciliano strncpy(options_fstype, items[0].value, sizeof(options_fstype)); 1181*ae2fc74fSJohn Baldwin newfs = newfs_command(options_fstype, 1); 11822118f387SNathan Whitehorn } 11832118f387SNathan Whitehorn 11842118f387SNathan Whitehorn size = maxsize; 118550e24496SAlfonso S. Siciliano if (strlen(items[1].value) > 0) { 118650e24496SAlfonso S. Siciliano if (expand_number(items[1].value, &bytes) != 0) { 11872118f387SNathan Whitehorn char error[512]; 11882118f387SNathan Whitehorn 11892118f387SNathan Whitehorn sprintf(error, "Invalid size: %s\n", strerror(errno)); 119050e24496SAlfonso S. Siciliano conf.title = "Error"; 119150e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, error, 0, 0); 11922118f387SNathan Whitehorn goto addpartform; 11932118f387SNathan Whitehorn } 11942118f387SNathan Whitehorn size = MIN((intmax_t)(bytes/sector), maxsize); 11952118f387SNathan Whitehorn } 11962118f387SNathan Whitehorn 11972118f387SNathan Whitehorn /* Check if the label has a / in it */ 119850e24496SAlfonso S. Siciliano if (items[3].value != NULL && strchr(items[3].value, '/') != NULL) { 119950e24496SAlfonso S. Siciliano conf.title = "Error"; 120050e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "Label contains a /, which is not an " 120150e24496SAlfonso S. Siciliano "allowed character.", 0, 0); 12022118f387SNathan Whitehorn goto addpartform; 12032118f387SNathan Whitehorn } 12042118f387SNathan Whitehorn 12052118f387SNathan Whitehorn /* Warn if no mountpoint set */ 120650e24496SAlfonso S. Siciliano if (strcmp(items[0].value, "freebsd-ufs") == 0 && 120750e24496SAlfonso S. Siciliano items[2].value[0] != '/') { 120840f0d8dcSRavi Pokala choice = 0; 120940f0d8dcSRavi Pokala if (interactive) { 121050e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 121150e24496SAlfonso S. Siciliano conf.title = "Warning"; 121250e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, 12132118f387SNathan Whitehorn "This partition does not have a valid mountpoint " 12142118f387SNathan Whitehorn "(for the partition from which you intend to boot the " 12152118f387SNathan Whitehorn "operating system, the mountpoint should be /). Are you " 12162118f387SNathan Whitehorn "sure you want to continue?" 12172118f387SNathan Whitehorn , 0, 0); 121850e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 121940f0d8dcSRavi Pokala } 122050e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 12212118f387SNathan Whitehorn goto addpartform; 12222118f387SNathan Whitehorn } 12232118f387SNathan Whitehorn 1224a780c996SNathan Whitehorn /* 1225a780c996SNathan Whitehorn * Error if this scheme needs nested partitions, this is one, and 1226a780c996SNathan Whitehorn * a mountpoint was set. 1227a780c996SNathan Whitehorn */ 122850e24496SAlfonso S. Siciliano if (strcmp(items[0].value, "freebsd") == 0 && 122950e24496SAlfonso S. Siciliano strlen(items[2].value) > 0) { 123050e24496SAlfonso S. Siciliano conf.title = "Error"; 123150e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "Partitions of type \"freebsd\" are " 1232a780c996SNathan Whitehorn "nested BSD-type partition schemes and cannot have " 1233a780c996SNathan Whitehorn "mountpoints. After creating one, select it and press " 123450e24496SAlfonso S. Siciliano "Create again to add the actual file systems.", 0, 0); 1235a780c996SNathan Whitehorn goto addpartform; 1236a780c996SNathan Whitehorn } 1237a780c996SNathan Whitehorn 12382118f387SNathan Whitehorn /* If this is the root partition, check that this scheme is bootable */ 123950e24496SAlfonso S. Siciliano if (strcmp(items[2].value, "/") == 0 && !is_scheme_bootable(scheme)) { 12402118f387SNathan Whitehorn char message[512]; 12412118f387SNathan Whitehorn sprintf(message, "This partition scheme (%s) is not bootable " 12422118f387SNathan Whitehorn "on this platform. Are you sure you want to proceed?", 12432118f387SNathan Whitehorn scheme); 124450e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 124550e24496SAlfonso S. Siciliano conf.title = "Warning"; 124650e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, message, 0, 0); 124750e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 124850e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 12492118f387SNathan Whitehorn goto addpartform; 12502118f387SNathan Whitehorn } 12512118f387SNathan Whitehorn 12526e15678aSNathan Whitehorn /* If this is the root partition, check that this fs is bootable */ 125350e24496SAlfonso S. Siciliano if (strcmp(items[2].value, "/") == 0 && !is_fs_bootable(scheme, 125450e24496SAlfonso S. Siciliano items[0].value)) { 12556e15678aSNathan Whitehorn char message[512]; 12566e15678aSNathan Whitehorn sprintf(message, "This file system (%s) is not bootable " 12576e15678aSNathan Whitehorn "on this system. Are you sure you want to proceed?", 125850e24496SAlfonso S. Siciliano items[0].value); 125950e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 126050e24496SAlfonso S. Siciliano conf.title = "Warning"; 126150e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, message, 0, 0); 126250e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 126350e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 12646e15678aSNathan Whitehorn goto addpartform; 12656e15678aSNathan Whitehorn } 12666e15678aSNathan Whitehorn 12672118f387SNathan Whitehorn /* 12682118f387SNathan Whitehorn * If this is the root partition, and we need a boot partition, ask 12692118f387SNathan Whitehorn * the user to add one. 12702118f387SNathan Whitehorn */ 1271a780c996SNathan Whitehorn 127250e24496SAlfonso S. Siciliano if ((strcmp(items[0].value, "freebsd") == 0 || 127350e24496SAlfonso S. Siciliano strcmp(items[2].value, "/") == 0) && bootpart_size(scheme) > 0) { 127452f39da1SNathan Whitehorn size_t bytes = add_boot_partition(geom, pp, scheme, 127552f39da1SNathan Whitehorn interactive); 12762118f387SNathan Whitehorn 12772118f387SNathan Whitehorn /* Now adjust the part we are really adding forward */ 127852f39da1SNathan Whitehorn if (bytes > 0) { 127952f39da1SNathan Whitehorn firstfree += bytes / sector; 128052f39da1SNathan Whitehorn size -= (bytes + stripe)/sector; 12812118f387SNathan Whitehorn if (stripe > 0 && (firstfree*sector % stripe) != 0) 12822118f387SNathan Whitehorn firstfree += (stripe - ((firstfree*sector) % 12832118f387SNathan Whitehorn stripe)) / sector; 12842118f387SNathan Whitehorn } 12852118f387SNathan Whitehorn } 12862118f387SNathan Whitehorn 12872117cdd4SAlexander Motin output[0] = '\0'; 12882117cdd4SAlexander Motin 12892118f387SNathan Whitehorn r = gctl_get_handle(); 12902118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 12912118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 12922118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 12932118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "add"); 129450e24496SAlfonso S. Siciliano 129550e24496SAlfonso S. Siciliano gctl_ro_param(r, "type", -1, items[0].value); 12962118f387SNathan Whitehorn snprintf(sizestr, sizeof(sizestr), "%jd", size); 12972118f387SNathan Whitehorn gctl_ro_param(r, "size", -1, sizestr); 12982118f387SNathan Whitehorn snprintf(startstr, sizeof(startstr), "%jd", firstfree); 12992118f387SNathan Whitehorn gctl_ro_param(r, "start", -1, startstr); 130050e24496SAlfonso S. Siciliano if (items[3].value != NULL && items[3].value[0] != '\0') 130150e24496SAlfonso S. Siciliano gctl_ro_param(r, "label", -1, items[3].value); 13022117cdd4SAlexander Motin gctl_add_param(r, "output", sizeof(output), output, 13032117cdd4SAlexander Motin GCTL_PARAM_WR | GCTL_PARAM_ASCII); 13042118f387SNathan Whitehorn errstr = gctl_issue(r); 13052118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 13062118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 13072118f387SNathan Whitehorn gctl_free(r); 13082118f387SNathan Whitehorn goto addpartform; 13092118f387SNathan Whitehorn } 13107899c6c1SNathan Whitehorn newpartname = strtok(output, " "); 13117899c6c1SNathan Whitehorn gctl_free(r); 13127899c6c1SNathan Whitehorn 13137899c6c1SNathan Whitehorn /* 13147899c6c1SNathan Whitehorn * Try to destroy any geom that gpart picked up already here from 13157899c6c1SNathan Whitehorn * dirty blocks. 13167899c6c1SNathan Whitehorn */ 13177899c6c1SNathan Whitehorn r = gctl_get_handle(); 13187899c6c1SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 13197899c6c1SNathan Whitehorn gctl_ro_param(r, "arg0", -1, newpartname); 13207899c6c1SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 13217899c6c1SNathan Whitehorn junk = 1; 13227899c6c1SNathan Whitehorn gctl_ro_param(r, "force", sizeof(junk), &junk); 13237899c6c1SNathan Whitehorn gctl_ro_param(r, "verb", -1, "destroy"); 13247899c6c1SNathan Whitehorn gctl_issue(r); /* Error usually expected and non-fatal */ 13257899c6c1SNathan Whitehorn gctl_free(r); 13262118f387SNathan Whitehorn 132752f39da1SNathan Whitehorn 132850e24496SAlfonso S. Siciliano if (strcmp(items[0].value, "freebsd") == 0) 13297899c6c1SNathan Whitehorn gpart_partition(newpartname, "BSD"); 13302118f387SNathan Whitehorn else 13317899c6c1SNathan Whitehorn set_default_part_metadata(newpartname, scheme, 133250e24496SAlfonso S. Siciliano items[0].value, items[2].value, newfs); 1333*ae2fc74fSJohn Baldwin free(newfs); 13342118f387SNathan Whitehorn 133550e24496SAlfonso S. Siciliano for (i = 0; i < nitems(items); i++) { 133650e24496SAlfonso S. Siciliano if (items[i].value != NULL) { 133750e24496SAlfonso S. Siciliano free(items[i].value); 133850e24496SAlfonso S. Siciliano if (init_allocated && items[i].init != NULL) 133950e24496SAlfonso S. Siciliano free((char*)items[i].init); 134050e24496SAlfonso S. Siciliano } 134150e24496SAlfonso S. Siciliano } 13422118f387SNathan Whitehorn 13432118f387SNathan Whitehorn if (partname != NULL) 13447899c6c1SNathan Whitehorn *partname = strdup(newpartname); 13452118f387SNathan Whitehorn } 13462118f387SNathan Whitehorn 13472118f387SNathan Whitehorn void 13482118f387SNathan Whitehorn gpart_delete(struct gprovider *pp) 13492118f387SNathan Whitehorn { 13502118f387SNathan Whitehorn struct gconfig *gc; 13512118f387SNathan Whitehorn struct ggeom *geom; 13522118f387SNathan Whitehorn struct gconsumer *cp; 13532118f387SNathan Whitehorn struct gctl_req *r; 13542118f387SNathan Whitehorn const char *errstr; 13552118f387SNathan Whitehorn intmax_t idx; 1356f36a5e0fSNathan Whitehorn int is_partition; 135750e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 13582118f387SNathan Whitehorn 13592118f387SNathan Whitehorn /* Is it a partition? */ 13602118f387SNathan Whitehorn is_partition = (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0); 13612118f387SNathan Whitehorn 13622118f387SNathan Whitehorn /* Find out if this is the root of a gpart geom */ 13632118f387SNathan Whitehorn geom = NULL; 13642118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 13652118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 13662118f387SNathan Whitehorn geom = cp->lg_geom; 13672118f387SNathan Whitehorn break; 13682118f387SNathan Whitehorn } 13692118f387SNathan Whitehorn 1370f36a5e0fSNathan Whitehorn /* If so, destroy all children */ 13712118f387SNathan Whitehorn if (geom != NULL) { 1372f36a5e0fSNathan Whitehorn gpart_destroy(geom); 1373f36a5e0fSNathan Whitehorn 1374f36a5e0fSNathan Whitehorn /* If this is a partition, revert it, so it can be deleted */ 13752118f387SNathan Whitehorn if (is_partition) { 1376f36a5e0fSNathan Whitehorn r = gctl_get_handle(); 1377f36a5e0fSNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 1378f36a5e0fSNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 1379f36a5e0fSNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 1380f36a5e0fSNathan Whitehorn gctl_issue(r); /* Ignore non-fatal errors */ 1381f36a5e0fSNathan Whitehorn gctl_free(r); 13822118f387SNathan Whitehorn } 13832118f387SNathan Whitehorn } 13842118f387SNathan Whitehorn 13852118f387SNathan Whitehorn /* 13862118f387SNathan Whitehorn * If this is not a partition, see if that is a problem, complain if 13872118f387SNathan Whitehorn * necessary, and return always, since we need not do anything further, 13882118f387SNathan Whitehorn * error or no. 13892118f387SNathan Whitehorn */ 13902118f387SNathan Whitehorn if (!is_partition) { 139150e24496SAlfonso S. Siciliano if (geom == NULL) { 139250e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 139350e24496SAlfonso S. Siciliano conf.title = "Error"; 139450e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, 139550e24496SAlfonso S. Siciliano "Only partitions can be deleted.", 0, 0); 139650e24496SAlfonso S. Siciliano } 13972118f387SNathan Whitehorn return; 13982118f387SNathan Whitehorn } 13992118f387SNathan Whitehorn 14002118f387SNathan Whitehorn r = gctl_get_handle(); 14012118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, pp->lg_geom->lg_class->lg_name); 14022118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); 14032118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 14042118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "delete"); 14052118f387SNathan Whitehorn 14062118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 14072118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 14082118f387SNathan Whitehorn idx = atoi(gc->lg_val); 14092118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 14102118f387SNathan Whitehorn break; 14112118f387SNathan Whitehorn } 14122118f387SNathan Whitehorn } 14132118f387SNathan Whitehorn 14142118f387SNathan Whitehorn errstr = gctl_issue(r); 14152118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 14162118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 14172118f387SNathan Whitehorn gctl_free(r); 14182118f387SNathan Whitehorn return; 14192118f387SNathan Whitehorn } 14202118f387SNathan Whitehorn 14212118f387SNathan Whitehorn gctl_free(r); 14222118f387SNathan Whitehorn 14232118f387SNathan Whitehorn delete_part_metadata(pp->lg_name); 14242118f387SNathan Whitehorn } 14252118f387SNathan Whitehorn 14262118f387SNathan Whitehorn void 14272118f387SNathan Whitehorn gpart_revert_all(struct gmesh *mesh) 14282118f387SNathan Whitehorn { 14292118f387SNathan Whitehorn struct gclass *classp; 14302118f387SNathan Whitehorn struct gconfig *gc; 14312118f387SNathan Whitehorn struct ggeom *gp; 14322118f387SNathan Whitehorn struct gctl_req *r; 14332118f387SNathan Whitehorn const char *modified; 143450e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 14352118f387SNathan Whitehorn 14362118f387SNathan Whitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 14372118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") == 0) 14382118f387SNathan Whitehorn break; 14392118f387SNathan Whitehorn } 14402118f387SNathan Whitehorn 14412118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") != 0) { 144250e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 144350e24496SAlfonso S. Siciliano conf.title = "Error"; 144450e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "gpart not found!", 0, 0); 14452118f387SNathan Whitehorn return; 14462118f387SNathan Whitehorn } 14472118f387SNathan Whitehorn 14482118f387SNathan Whitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 14492118f387SNathan Whitehorn modified = "true"; /* XXX: If we don't know (kernel too old), 14502118f387SNathan Whitehorn * assume there are modifications. */ 14512118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 14522118f387SNathan Whitehorn if (strcmp(gc->lg_name, "modified") == 0) { 14532118f387SNathan Whitehorn modified = gc->lg_val; 14542118f387SNathan Whitehorn break; 14552118f387SNathan Whitehorn } 14562118f387SNathan Whitehorn } 14572118f387SNathan Whitehorn 14582118f387SNathan Whitehorn if (strcmp(modified, "false") == 0) 14592118f387SNathan Whitehorn continue; 14602118f387SNathan Whitehorn 14612118f387SNathan Whitehorn r = gctl_get_handle(); 14622118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 14632118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 14642118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 14652118f387SNathan Whitehorn 14667899c6c1SNathan Whitehorn gctl_issue(r); 14672118f387SNathan Whitehorn gctl_free(r); 14682118f387SNathan Whitehorn } 14692118f387SNathan Whitehorn } 14702118f387SNathan Whitehorn 14712118f387SNathan Whitehorn void 14722118f387SNathan Whitehorn gpart_commit(struct gmesh *mesh) 14732118f387SNathan Whitehorn { 14742118f387SNathan Whitehorn struct partition_metadata *md; 14752118f387SNathan Whitehorn struct gclass *classp; 14762118f387SNathan Whitehorn struct ggeom *gp; 14772118f387SNathan Whitehorn struct gconfig *gc; 14782118f387SNathan Whitehorn struct gconsumer *cp; 14792118f387SNathan Whitehorn struct gprovider *pp; 14802118f387SNathan Whitehorn struct gctl_req *r; 14812118f387SNathan Whitehorn const char *errstr; 14822118f387SNathan Whitehorn const char *modified; 14836e15678aSNathan Whitehorn const char *rootfs; 148450e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 14852118f387SNathan Whitehorn 14862118f387SNathan Whitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 14872118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") == 0) 14882118f387SNathan Whitehorn break; 14892118f387SNathan Whitehorn } 14902118f387SNathan Whitehorn 14916e15678aSNathan Whitehorn /* Figure out what filesystem / uses */ 14926e15678aSNathan Whitehorn rootfs = "ufs"; /* Assume ufs if nothing else present */ 14936e15678aSNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 14946e15678aSNathan Whitehorn if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) { 14956e15678aSNathan Whitehorn rootfs = md->fstab->fs_vfstype; 14966e15678aSNathan Whitehorn break; 14976e15678aSNathan Whitehorn } 14986e15678aSNathan Whitehorn } 14996e15678aSNathan Whitehorn 15002118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") != 0) { 150150e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 150250e24496SAlfonso S. Siciliano conf.title = "Error"; 150350e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "gpart not found!", 0, 0); 15042118f387SNathan Whitehorn return; 15052118f387SNathan Whitehorn } 15062118f387SNathan Whitehorn 15072118f387SNathan Whitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 15082118f387SNathan Whitehorn modified = "true"; /* XXX: If we don't know (kernel too old), 15092118f387SNathan Whitehorn * assume there are modifications. */ 15102118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 15112118f387SNathan Whitehorn if (strcmp(gc->lg_name, "modified") == 0) { 15122118f387SNathan Whitehorn modified = gc->lg_val; 15132118f387SNathan Whitehorn break; 15142118f387SNathan Whitehorn } 15152118f387SNathan Whitehorn } 15162118f387SNathan Whitehorn 15172118f387SNathan Whitehorn if (strcmp(modified, "false") == 0) 15182118f387SNathan Whitehorn continue; 15192118f387SNathan Whitehorn 15202118f387SNathan Whitehorn /* Add bootcode if necessary, before the commit */ 15212118f387SNathan Whitehorn md = get_part_metadata(gp->lg_name, 0); 15222118f387SNathan Whitehorn if (md != NULL && md->bootcode) 15232118f387SNathan Whitehorn gpart_bootcode(gp); 15242118f387SNathan Whitehorn 15252118f387SNathan Whitehorn /* Now install partcode on its partitions, if necessary */ 15262118f387SNathan Whitehorn LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 15272118f387SNathan Whitehorn md = get_part_metadata(pp->lg_name, 0); 15282118f387SNathan Whitehorn if (md == NULL || !md->bootcode) 15292118f387SNathan Whitehorn continue; 15302118f387SNathan Whitehorn 15312118f387SNathan Whitehorn /* Mark this partition active if that's required */ 15322118f387SNathan Whitehorn gpart_activate(pp); 15332118f387SNathan Whitehorn 15342118f387SNathan Whitehorn /* Check if the partition has sub-partitions */ 15352118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 15362118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, 15372118f387SNathan Whitehorn "PART") == 0) 15382118f387SNathan Whitehorn break; 15392118f387SNathan Whitehorn 15402118f387SNathan Whitehorn if (cp == NULL) /* No sub-partitions */ 15416e15678aSNathan Whitehorn gpart_partcode(pp, rootfs); 15422118f387SNathan Whitehorn } 15432118f387SNathan Whitehorn 15442118f387SNathan Whitehorn r = gctl_get_handle(); 15452118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 15462118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 15472118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "commit"); 15482118f387SNathan Whitehorn 15492118f387SNathan Whitehorn errstr = gctl_issue(r); 15502118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 15512118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 15522118f387SNathan Whitehorn gctl_free(r); 15532118f387SNathan Whitehorn } 15542118f387SNathan Whitehorn } 15552118f387SNathan Whitehorn 1556