12118f387SNathan Whitehorn /*- 2*4d846d26SWarner 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 * $FreeBSD$ 292118f387SNathan Whitehorn */ 302118f387SNathan Whitehorn 312118f387SNathan Whitehorn #include <sys/param.h> 326e15678aSNathan Whitehorn #include <sys/stat.h> 3350e24496SAlfonso S. Siciliano 3450e24496SAlfonso S. Siciliano #include <bsddialog.h> 3550e24496SAlfonso S. Siciliano #include <ctype.h> 362118f387SNathan Whitehorn #include <errno.h> 37db8b5613SRebecca Cran #include <fcntl.h> 382118f387SNathan Whitehorn #include <libutil.h> 392118f387SNathan Whitehorn #include <inttypes.h> 4050e24496SAlfonso S. Siciliano #include <stdio.h> 4150e24496SAlfonso S. Siciliano #include <stdlib.h> 4250e24496SAlfonso S. Siciliano #include <string.h> 4350e24496SAlfonso S. Siciliano #include <unistd.h> 442118f387SNathan Whitehorn 452118f387SNathan Whitehorn #include <libgeom.h> 462118f387SNathan Whitehorn 472118f387SNathan Whitehorn #include "partedit.h" 482118f387SNathan Whitehorn 492118f387SNathan Whitehorn #define GPART_FLAGS "x" /* Do not commit changes by default */ 502118f387SNathan Whitehorn 512118f387SNathan Whitehorn static void 522118f387SNathan Whitehorn gpart_show_error(const char *title, const char *explanation, const char *errstr) 532118f387SNathan Whitehorn { 542118f387SNathan Whitehorn char *errmsg; 552118f387SNathan Whitehorn char message[512]; 562118f387SNathan Whitehorn int error; 5750e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 582118f387SNathan Whitehorn 592118f387SNathan Whitehorn if (explanation == NULL) 602118f387SNathan Whitehorn explanation = ""; 612118f387SNathan Whitehorn 622118f387SNathan Whitehorn error = strtol(errstr, &errmsg, 0); 632118f387SNathan Whitehorn if (errmsg != errstr) { 642118f387SNathan Whitehorn while (errmsg[0] == ' ') 652118f387SNathan Whitehorn errmsg++; 662118f387SNathan Whitehorn if (errmsg[0] != '\0') 672118f387SNathan Whitehorn sprintf(message, "%s%s. %s", explanation, 682118f387SNathan Whitehorn strerror(error), errmsg); 692118f387SNathan Whitehorn else 702118f387SNathan Whitehorn sprintf(message, "%s%s", explanation, strerror(error)); 712118f387SNathan Whitehorn } else { 722118f387SNathan Whitehorn sprintf(message, "%s%s", explanation, errmsg); 732118f387SNathan Whitehorn } 742118f387SNathan Whitehorn 7550e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 7650e24496SAlfonso S. Siciliano conf.title = title; 7750e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, message, 0, 0); 782118f387SNathan Whitehorn } 792118f387SNathan Whitehorn 80c67f41d0SNathan Whitehorn static int 81c67f41d0SNathan Whitehorn scheme_supports_labels(const char *scheme) 82c67f41d0SNathan Whitehorn { 83c67f41d0SNathan Whitehorn if (strcmp(scheme, "APM") == 0) 84c67f41d0SNathan Whitehorn return (1); 85c67f41d0SNathan Whitehorn if (strcmp(scheme, "GPT") == 0) 86c67f41d0SNathan Whitehorn return (1); 87c67f41d0SNathan Whitehorn 88c67f41d0SNathan Whitehorn return (0); 89c67f41d0SNathan Whitehorn } 90c67f41d0SNathan Whitehorn 9150de5d07SNathan Whitehorn static void 9250de5d07SNathan Whitehorn newfs_command(const char *fstype, char *command, int use_default) 9350de5d07SNathan Whitehorn { 9450e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 9550e24496SAlfonso S. Siciliano 9650e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 9750e24496SAlfonso S. Siciliano 9850de5d07SNathan Whitehorn if (strcmp(fstype, "freebsd-ufs") == 0) { 9950de5d07SNathan Whitehorn int i; 10050e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 10150e24496SAlfonso S. Siciliano {"", false, 0, "UFS1", "UFS Version 1", 10250de5d07SNathan Whitehorn "Use version 1 of the UFS file system instead " 10350e24496SAlfonso S. Siciliano "of version 2 (not recommended)"}, 10450e24496SAlfonso S. Siciliano {"", true, 0, "SU", "Softupdates", 10550e24496SAlfonso S. Siciliano "Enable softupdates (default)"}, 10650e24496SAlfonso S. Siciliano {"", true, 0, "SUJ", "Softupdates journaling", 1074a8b3e41SEd Maste "Enable file system journaling (default - " 10850e24496SAlfonso S. Siciliano "turn off for SSDs)"}, 10950e24496SAlfonso S. Siciliano {"", false, 0, "TRIM", "Enable SSD TRIM support", 11050e24496SAlfonso S. Siciliano "Enable TRIM support, useful on solid-state " 11150e24496SAlfonso S. Siciliano "drives" }, 11250de5d07SNathan Whitehorn }; 11350de5d07SNathan Whitehorn 11450de5d07SNathan Whitehorn if (!use_default) { 11550de5d07SNathan Whitehorn int choice; 11650e24496SAlfonso S. Siciliano conf.title = "UFS Options"; 11750e24496SAlfonso S. Siciliano choice = bsddialog_checklist(&conf, "", 0, 0, 0, 11850e24496SAlfonso S. Siciliano nitems(items), items, NULL); 11950e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 12050de5d07SNathan Whitehorn return; 12150de5d07SNathan Whitehorn } 12250de5d07SNathan Whitehorn 12350de5d07SNathan Whitehorn strcpy(command, "newfs "); 12463128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 12550e24496SAlfonso S. Siciliano if (items[i].on == false) 12650de5d07SNathan Whitehorn continue; 12750de5d07SNathan Whitehorn if (strcmp(items[i].name, "UFS1") == 0) 12850de5d07SNathan Whitehorn strcat(command, "-O1 "); 12950de5d07SNathan Whitehorn else if (strcmp(items[i].name, "SU") == 0) 13050de5d07SNathan Whitehorn strcat(command, "-U "); 13150de5d07SNathan Whitehorn else if (strcmp(items[i].name, "SUJ") == 0) 13250de5d07SNathan Whitehorn strcat(command, "-j "); 13350de5d07SNathan Whitehorn else if (strcmp(items[i].name, "TRIM") == 0) 13450de5d07SNathan Whitehorn strcat(command, "-t "); 13550de5d07SNathan Whitehorn } 1366e15678aSNathan Whitehorn } else if (strcmp(fstype, "freebsd-zfs") == 0) { 1376e15678aSNathan Whitehorn int i; 13850e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 13950e24496SAlfonso S. Siciliano {"", 0, true, "fletcher4", "checksum algorithm: fletcher4", 1406e15678aSNathan Whitehorn "Use fletcher4 for data integrity checking. " 14150e24496SAlfonso S. Siciliano "(default)"}, 14250e24496SAlfonso S. Siciliano {"", 0, false, "fletcher2", "checksum algorithm: fletcher2", 1436e15678aSNathan Whitehorn "Use fletcher2 for data integrity checking. " 14450e24496SAlfonso S. Siciliano "(not recommended)"}, 14550e24496SAlfonso S. Siciliano {"", 0, false, "sha256", "checksum algorithm: sha256", 1466e15678aSNathan Whitehorn "Use sha256 for data integrity checking. " 14750e24496SAlfonso S. Siciliano "(not recommended)"}, 14850e24496SAlfonso S. Siciliano {"", 0, false, "atime", "Update atimes for files", 14950e24496SAlfonso S. Siciliano "Disable atime update"}, 1506e15678aSNathan Whitehorn }; 1516e15678aSNathan Whitehorn 1526e15678aSNathan Whitehorn if (!use_default) { 1536e15678aSNathan Whitehorn int choice; 15450e24496SAlfonso S. Siciliano conf.title = "ZFS Options"; 15550e24496SAlfonso S. Siciliano choice = bsddialog_checklist(&conf, "", 0, 0, 0, 15650e24496SAlfonso S. Siciliano nitems(items), items, NULL); 15750e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 1586e15678aSNathan Whitehorn return; 1596e15678aSNathan Whitehorn } 1606e15678aSNathan Whitehorn 1616e15678aSNathan Whitehorn strcpy(command, "zpool create -f -m none "); 1626e15678aSNathan Whitehorn if (getenv("BSDINSTALL_TMPBOOT") != NULL) { 1636e15678aSNathan Whitehorn char zfsboot_path[MAXPATHLEN]; 1646c546e77SConrad Meyer snprintf(zfsboot_path, sizeof(zfsboot_path), "%s/zfs", 1656e15678aSNathan Whitehorn getenv("BSDINSTALL_TMPBOOT")); 1666e15678aSNathan Whitehorn mkdir(zfsboot_path, S_IRWXU | S_IRGRP | S_IXGRP | 1676e15678aSNathan Whitehorn S_IROTH | S_IXOTH); 1686e15678aSNathan Whitehorn sprintf(command, "%s -o cachefile=%s/zpool.cache ", 1696e15678aSNathan Whitehorn command, zfsboot_path); 1706e15678aSNathan Whitehorn } 17163128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 17250e24496SAlfonso S. Siciliano if (items[i].on == false) 1736e15678aSNathan Whitehorn continue; 1746e15678aSNathan Whitehorn if (strcmp(items[i].name, "fletcher4") == 0) 1756e15678aSNathan Whitehorn strcat(command, "-O checksum=fletcher4 "); 1766e15678aSNathan Whitehorn else if (strcmp(items[i].name, "fletcher2") == 0) 1776e15678aSNathan Whitehorn strcat(command, "-O checksum=fletcher2 "); 1786e15678aSNathan Whitehorn else if (strcmp(items[i].name, "sha256") == 0) 1796e15678aSNathan Whitehorn strcat(command, "-O checksum=sha256 "); 1806e15678aSNathan Whitehorn else if (strcmp(items[i].name, "atime") == 0) 1816e15678aSNathan Whitehorn strcat(command, "-O atime=off "); 1826e15678aSNathan Whitehorn } 1839f7602f0SNathan Whitehorn } else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0 || 1849f7602f0SNathan Whitehorn strcmp(fstype, "ms-basic-data") == 0) { 18550de5d07SNathan Whitehorn int i; 18650e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 18750e24496SAlfonso S. Siciliano {"", 0, true, "FAT32", "FAT Type 32", 18850e24496SAlfonso S. Siciliano "Create a FAT32 filesystem (default)"}, 18950e24496SAlfonso S. Siciliano {"", 0, false, "FAT16", "FAT Type 16", 19050e24496SAlfonso S. Siciliano "Create a FAT16 filesystem"}, 19150e24496SAlfonso S. Siciliano {"", 0, false, "FAT12", "FAT Type 12", 19250e24496SAlfonso S. Siciliano "Create a FAT12 filesystem"}, 19350de5d07SNathan Whitehorn }; 19450de5d07SNathan Whitehorn 19550de5d07SNathan Whitehorn if (!use_default) { 19650de5d07SNathan Whitehorn int choice; 19750e24496SAlfonso S. Siciliano conf.title = "FAT Options"; 19850e24496SAlfonso S. Siciliano choice = bsddialog_radiolist(&conf, "", 0, 0, 0, 19950e24496SAlfonso S. Siciliano nitems(items), items, NULL); 20050e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 20150de5d07SNathan Whitehorn return; 20250de5d07SNathan Whitehorn } 20350de5d07SNathan Whitehorn 20450de5d07SNathan Whitehorn strcpy(command, "newfs_msdos "); 20563128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 20650e24496SAlfonso S. Siciliano if (items[i].on == false) 20750de5d07SNathan Whitehorn continue; 208db8b5613SRebecca Cran if (strcmp(items[i].name, "FAT32") == 0) 209db8b5613SRebecca Cran strcat(command, "-F 32 -c 1"); 210db8b5613SRebecca Cran else if (strcmp(items[i].name, "FAT16") == 0) 21150de5d07SNathan Whitehorn strcat(command, "-F 16 "); 212ae2e7abfSNathan Whitehorn else if (strcmp(items[i].name, "FAT12") == 0) 21350de5d07SNathan Whitehorn strcat(command, "-F 12 "); 21450de5d07SNathan Whitehorn } 21550de5d07SNathan Whitehorn } else { 21650e24496SAlfonso S. Siciliano if (!use_default) { 21750e24496SAlfonso S. Siciliano conf.title = "Error"; 21850e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "No configurable options exist " 21950e24496SAlfonso S. Siciliano "for this filesystem.", 0, 0); 22050e24496SAlfonso S. Siciliano } 22150de5d07SNathan Whitehorn command[0] = '\0'; 22250de5d07SNathan Whitehorn } 22350de5d07SNathan Whitehorn } 22450de5d07SNathan Whitehorn 2257059fa6fSAllan Jude const char * 2267059fa6fSAllan Jude choose_part_type(const char *def_scheme) 2272118f387SNathan Whitehorn { 22850e24496SAlfonso S. Siciliano int button, choice, i; 2297059fa6fSAllan Jude const char *scheme = NULL; 23050e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 2312118f387SNathan Whitehorn 23250e24496SAlfonso S. Siciliano struct bsddialog_menuitem items[] = { 23350e24496SAlfonso S. Siciliano {"", false, 0, "APM", "Apple Partition Map", 23450e24496SAlfonso S. Siciliano "Bootable on PowerPC Apple Hardware" }, 23550e24496SAlfonso S. Siciliano {"", false, 0, "BSD", "BSD Labels", 23650e24496SAlfonso S. Siciliano "Bootable on most x86 systems" }, 23750e24496SAlfonso S. Siciliano {"", false, 0, "GPT", "GUID Partition Table", 23850e24496SAlfonso S. Siciliano "Bootable on most x86 systems and EFI aware ARM64" }, 23950e24496SAlfonso S. Siciliano {"", false, 0, "MBR", "DOS Partitions", 24050e24496SAlfonso S. Siciliano "Bootable on most x86 systems" }, 2412118f387SNathan Whitehorn }; 2422118f387SNathan Whitehorn 24350e24496SAlfonso S. Siciliano for (i = 0; i < (int)nitems(items); i++) 24450e24496SAlfonso S. Siciliano if (strcmp(items[i].name, def_scheme) == 0) 24550e24496SAlfonso S. Siciliano choice = i; 2462118f387SNathan Whitehorn 24750e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 24850e24496SAlfonso S. Siciliano 24950e24496SAlfonso S. Siciliano parttypemenu: 25050e24496SAlfonso S. Siciliano conf.title = "Partition Scheme"; 25150e24496SAlfonso S. Siciliano button = bsddialog_menu(&conf, 25250e24496SAlfonso S. Siciliano "Select a partition scheme for this volume:", 0, 0, 0, 25350e24496SAlfonso S. Siciliano nitems(items), items, &choice); 25450e24496SAlfonso S. Siciliano 25550e24496SAlfonso S. Siciliano if (button == BSDDIALOG_CANCEL) 2567059fa6fSAllan Jude return NULL; 2572118f387SNathan Whitehorn 2582118f387SNathan Whitehorn if (!is_scheme_bootable(items[choice].name)) { 2592118f387SNathan Whitehorn char message[512]; 2602118f387SNathan Whitehorn sprintf(message, "This partition scheme (%s) is not " 2612118f387SNathan Whitehorn "bootable on this platform. Are you sure you want " 2622118f387SNathan Whitehorn "to proceed?", items[choice].name); 26350e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 26450e24496SAlfonso S. Siciliano conf.title = "Warning"; 26550e24496SAlfonso S. Siciliano button = bsddialog_yesno(&conf, message, 0, 0); 26650e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 26750e24496SAlfonso S. Siciliano if (button == BSDDIALOG_NO) 2687059fa6fSAllan Jude goto parttypemenu; 2692118f387SNathan Whitehorn } 2702118f387SNathan Whitehorn 2712118f387SNathan Whitehorn scheme = items[choice].name; 2727059fa6fSAllan Jude 2737059fa6fSAllan Jude return scheme; 2747059fa6fSAllan Jude } 2757059fa6fSAllan Jude 2767059fa6fSAllan Jude int 2777059fa6fSAllan Jude gpart_partition(const char *lg_name, const char *scheme) 2787059fa6fSAllan Jude { 27950e24496SAlfonso S. Siciliano int button; 2807059fa6fSAllan Jude struct gctl_req *r; 2817059fa6fSAllan Jude const char *errstr; 28250e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 28350e24496SAlfonso S. Siciliano 28450e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 2857059fa6fSAllan Jude 2867059fa6fSAllan Jude schememenu: 2877059fa6fSAllan Jude if (scheme == NULL) { 2887059fa6fSAllan Jude scheme = choose_part_type(default_scheme()); 2897059fa6fSAllan Jude 2907059fa6fSAllan Jude if (scheme == NULL) 2917059fa6fSAllan Jude return (-1); 2927059fa6fSAllan Jude 2937059fa6fSAllan Jude if (!is_scheme_bootable(scheme)) { 2947059fa6fSAllan Jude char message[512]; 2957059fa6fSAllan Jude sprintf(message, "This partition scheme (%s) is not " 2967059fa6fSAllan Jude "bootable on this platform. Are you sure you want " 2977059fa6fSAllan Jude "to proceed?", scheme); 29850e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 29950e24496SAlfonso S. Siciliano conf.title = "Warning"; 30050e24496SAlfonso S. Siciliano button = bsddialog_yesno(&conf, message, 0, 0); 30150e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 30250e24496SAlfonso S. Siciliano if (button == BSDDIALOG_NO) { 3037059fa6fSAllan Jude /* Reset scheme so user can choose another */ 3047059fa6fSAllan Jude scheme = NULL; 3057059fa6fSAllan Jude goto schememenu; 3067059fa6fSAllan Jude } 3077059fa6fSAllan Jude } 3082118f387SNathan Whitehorn } 3092118f387SNathan Whitehorn 3102118f387SNathan Whitehorn r = gctl_get_handle(); 3112118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 3122118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_name); 3132118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 3142118f387SNathan Whitehorn gctl_ro_param(r, "scheme", -1, scheme); 3152118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "create"); 3162118f387SNathan Whitehorn 3172118f387SNathan Whitehorn errstr = gctl_issue(r); 3182118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 3192118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 3202118f387SNathan Whitehorn gctl_free(r); 3212118f387SNathan Whitehorn scheme = NULL; 3222118f387SNathan Whitehorn goto schememenu; 3232118f387SNathan Whitehorn } 3242118f387SNathan Whitehorn gctl_free(r); 3252118f387SNathan Whitehorn 3262118f387SNathan Whitehorn if (bootcode_path(scheme) != NULL) 3272118f387SNathan Whitehorn get_part_metadata(lg_name, 1)->bootcode = 1; 3282118f387SNathan Whitehorn return (0); 3292118f387SNathan Whitehorn } 3302118f387SNathan Whitehorn 3312118f387SNathan Whitehorn static void 3322118f387SNathan Whitehorn gpart_activate(struct gprovider *pp) 3332118f387SNathan Whitehorn { 3342118f387SNathan Whitehorn struct gconfig *gc; 3352118f387SNathan Whitehorn struct gctl_req *r; 3362118f387SNathan Whitehorn const char *errstr, *scheme; 3372118f387SNathan Whitehorn const char *attribute = NULL; 3382118f387SNathan Whitehorn intmax_t idx; 3392118f387SNathan Whitehorn 3402118f387SNathan Whitehorn /* 3412118f387SNathan Whitehorn * Some partition schemes need this partition to be marked 'active' 3422118f387SNathan Whitehorn * for it to be bootable. 3432118f387SNathan Whitehorn */ 3442118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { 3452118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 3462118f387SNathan Whitehorn scheme = gc->lg_val; 3472118f387SNathan Whitehorn break; 3482118f387SNathan Whitehorn } 3492118f387SNathan Whitehorn } 3502118f387SNathan Whitehorn 3512b375b4eSYoshihiro Takahashi if (strcmp(scheme, "MBR") == 0 || strcmp(scheme, "EBR") == 0) 3522118f387SNathan Whitehorn attribute = "active"; 3532118f387SNathan Whitehorn else 3542118f387SNathan Whitehorn return; 3552118f387SNathan Whitehorn 3562118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 3572118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 3582118f387SNathan Whitehorn idx = atoi(gc->lg_val); 3592118f387SNathan Whitehorn break; 3602118f387SNathan Whitehorn } 3612118f387SNathan Whitehorn } 3622118f387SNathan Whitehorn 3632118f387SNathan Whitehorn r = gctl_get_handle(); 3642118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 3652118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); 3662118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "set"); 3672118f387SNathan Whitehorn gctl_ro_param(r, "attrib", -1, attribute); 3682118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 3692118f387SNathan Whitehorn 3702118f387SNathan Whitehorn errstr = gctl_issue(r); 3712118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 3722118f387SNathan Whitehorn gpart_show_error("Error", "Error marking partition active:", 3732118f387SNathan Whitehorn errstr); 3742118f387SNathan Whitehorn gctl_free(r); 3752118f387SNathan Whitehorn } 3762118f387SNathan Whitehorn 3777059fa6fSAllan Jude void 3787059fa6fSAllan Jude gpart_set_root(const char *lg_name, const char *attribute) 3797059fa6fSAllan Jude { 3807059fa6fSAllan Jude struct gctl_req *r; 3817059fa6fSAllan Jude const char *errstr; 3827059fa6fSAllan Jude 3837059fa6fSAllan Jude r = gctl_get_handle(); 3847059fa6fSAllan Jude gctl_ro_param(r, "class", -1, "PART"); 3857059fa6fSAllan Jude gctl_ro_param(r, "arg0", -1, lg_name); 3867059fa6fSAllan Jude gctl_ro_param(r, "flags", -1, "C"); 3877059fa6fSAllan Jude gctl_ro_param(r, "verb", -1, "set"); 3887059fa6fSAllan Jude gctl_ro_param(r, "attrib", -1, attribute); 3897059fa6fSAllan Jude 3907059fa6fSAllan Jude errstr = gctl_issue(r); 3917059fa6fSAllan Jude if (errstr != NULL && errstr[0] != '\0') 3927059fa6fSAllan Jude gpart_show_error("Error", "Error setting parameter on disk:", 3937059fa6fSAllan Jude errstr); 3947059fa6fSAllan Jude gctl_free(r); 3957059fa6fSAllan Jude } 3967059fa6fSAllan Jude 3972118f387SNathan Whitehorn static void 3982118f387SNathan Whitehorn gpart_bootcode(struct ggeom *gp) 3992118f387SNathan Whitehorn { 4002118f387SNathan Whitehorn const char *bootcode; 4012118f387SNathan Whitehorn struct gconfig *gc; 4022118f387SNathan Whitehorn struct gctl_req *r; 4032118f387SNathan Whitehorn const char *errstr, *scheme; 4042118f387SNathan Whitehorn uint8_t *boot; 4052118f387SNathan Whitehorn size_t bootsize, bytes; 4062118f387SNathan Whitehorn int bootfd; 40750e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 4082118f387SNathan Whitehorn 4092118f387SNathan Whitehorn /* 4102118f387SNathan Whitehorn * Write default bootcode to the newly partitioned disk, if that 4112118f387SNathan Whitehorn * applies on this platform. 4122118f387SNathan Whitehorn */ 4132118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 4142118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 4152118f387SNathan Whitehorn scheme = gc->lg_val; 4162118f387SNathan Whitehorn break; 4172118f387SNathan Whitehorn } 4182118f387SNathan Whitehorn } 4192118f387SNathan Whitehorn 4202118f387SNathan Whitehorn bootcode = bootcode_path(scheme); 4212118f387SNathan Whitehorn if (bootcode == NULL) 4222118f387SNathan Whitehorn return; 4232118f387SNathan Whitehorn 4242118f387SNathan Whitehorn bootfd = open(bootcode, O_RDONLY); 425c725e3efSKevin Lo if (bootfd < 0) { 42650e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 42750e24496SAlfonso S. Siciliano conf.title = "Bootcode Error"; 42850e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, strerror(errno), 0, 0); 4292118f387SNathan Whitehorn return; 4302118f387SNathan Whitehorn } 4312118f387SNathan Whitehorn 4322118f387SNathan Whitehorn bootsize = lseek(bootfd, 0, SEEK_END); 4332118f387SNathan Whitehorn boot = malloc(bootsize); 4342118f387SNathan Whitehorn lseek(bootfd, 0, SEEK_SET); 4352118f387SNathan Whitehorn bytes = 0; 4362118f387SNathan Whitehorn while (bytes < bootsize) 4372118f387SNathan Whitehorn bytes += read(bootfd, boot + bytes, bootsize - bytes); 4382118f387SNathan Whitehorn close(bootfd); 4392118f387SNathan Whitehorn 4402118f387SNathan Whitehorn r = gctl_get_handle(); 4412118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 4422118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 4432118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "bootcode"); 4442118f387SNathan Whitehorn gctl_ro_param(r, "bootcode", bootsize, boot); 4452118f387SNathan Whitehorn 4462118f387SNathan Whitehorn errstr = gctl_issue(r); 4472118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 4482118f387SNathan Whitehorn gpart_show_error("Bootcode Error", NULL, errstr); 4492118f387SNathan Whitehorn gctl_free(r); 4502118f387SNathan Whitehorn free(boot); 4512118f387SNathan Whitehorn } 4522118f387SNathan Whitehorn 4532118f387SNathan Whitehorn static void 4546e15678aSNathan Whitehorn gpart_partcode(struct gprovider *pp, const char *fstype) 4552118f387SNathan Whitehorn { 4562118f387SNathan Whitehorn struct gconfig *gc; 4572118f387SNathan Whitehorn const char *scheme; 4582118f387SNathan Whitehorn const char *indexstr; 4592118f387SNathan Whitehorn char message[255], command[255]; 46050e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 4612118f387SNathan Whitehorn 4622118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { 4632118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 4642118f387SNathan Whitehorn scheme = gc->lg_val; 4652118f387SNathan Whitehorn break; 4662118f387SNathan Whitehorn } 4672118f387SNathan Whitehorn } 4682118f387SNathan Whitehorn 4692118f387SNathan Whitehorn /* Make sure this partition scheme needs partcode on this platform */ 4706e15678aSNathan Whitehorn if (partcode_path(scheme, fstype) == NULL) 4712118f387SNathan Whitehorn return; 4722118f387SNathan Whitehorn 4732118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 4742118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 4752118f387SNathan Whitehorn indexstr = gc->lg_val; 4762118f387SNathan Whitehorn break; 4772118f387SNathan Whitehorn } 4782118f387SNathan Whitehorn } 4792118f387SNathan Whitehorn 4802118f387SNathan Whitehorn /* Shell out to gpart for partcode for now */ 4812118f387SNathan Whitehorn sprintf(command, "gpart bootcode -p %s -i %s %s", 4826e15678aSNathan Whitehorn partcode_path(scheme, fstype), indexstr, pp->lg_geom->lg_name); 4832118f387SNathan Whitehorn if (system(command) != 0) { 4842118f387SNathan Whitehorn sprintf(message, "Error installing partcode on partition %s", 4852118f387SNathan Whitehorn pp->lg_name); 48650e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 48750e24496SAlfonso S. Siciliano conf.title = "Error"; 48850e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, message, 0, 0); 4892118f387SNathan Whitehorn } 4902118f387SNathan Whitehorn } 4912118f387SNathan Whitehorn 4922118f387SNathan Whitehorn void 493f36a5e0fSNathan Whitehorn gpart_destroy(struct ggeom *lg_geom) 4942118f387SNathan Whitehorn { 4952118f387SNathan Whitehorn struct gctl_req *r; 496f36a5e0fSNathan Whitehorn struct gprovider *pp; 4972118f387SNathan Whitehorn const char *errstr; 498f36a5e0fSNathan Whitehorn int force = 1; 4992118f387SNathan Whitehorn 500f36a5e0fSNathan Whitehorn /* Delete all child metadata */ 5012118f387SNathan Whitehorn LIST_FOREACH(pp, &lg_geom->lg_provider, lg_provider) 5022118f387SNathan Whitehorn gpart_delete(pp); 5032118f387SNathan Whitehorn 504f36a5e0fSNathan Whitehorn /* Revert any local changes to get this geom into a pristine state */ 505f36a5e0fSNathan Whitehorn r = gctl_get_handle(); 506f36a5e0fSNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 507f36a5e0fSNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); 508f36a5e0fSNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 509f36a5e0fSNathan Whitehorn gctl_issue(r); /* Ignore errors -- these are non-fatal */ 510f36a5e0fSNathan Whitehorn gctl_free(r); 511f36a5e0fSNathan Whitehorn 5122118f387SNathan Whitehorn /* Now destroy the geom itself */ 5132118f387SNathan Whitehorn r = gctl_get_handle(); 5142118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 5152118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); 5162118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 517f36a5e0fSNathan Whitehorn gctl_ro_param(r, "force", sizeof(force), &force); 5182118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "destroy"); 5192118f387SNathan Whitehorn errstr = gctl_issue(r); 520987415b1SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 521987415b1SNathan Whitehorn /* 522987415b1SNathan Whitehorn * Check if we reverted away the existence of the geom 523987415b1SNathan Whitehorn * altogether. Show all other errors to the user. 524987415b1SNathan Whitehorn */ 525987415b1SNathan Whitehorn if (strtol(errstr, NULL, 0) != EINVAL) 5262118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 527987415b1SNathan Whitehorn } 5282118f387SNathan Whitehorn gctl_free(r); 5292118f387SNathan Whitehorn 5302118f387SNathan Whitehorn /* And any metadata associated with the partition scheme itself */ 5312118f387SNathan Whitehorn delete_part_metadata(lg_geom->lg_name); 5322118f387SNathan Whitehorn } 5332118f387SNathan Whitehorn 5342118f387SNathan Whitehorn void 5352118f387SNathan Whitehorn gpart_edit(struct gprovider *pp) 5362118f387SNathan Whitehorn { 5372118f387SNathan Whitehorn struct gctl_req *r; 5382118f387SNathan Whitehorn struct gconfig *gc; 5392118f387SNathan Whitehorn struct gconsumer *cp; 5402118f387SNathan Whitehorn struct ggeom *geom; 5412118f387SNathan Whitehorn const char *errstr, *oldtype, *scheme; 5422118f387SNathan Whitehorn struct partition_metadata *md; 5432118f387SNathan Whitehorn char sizestr[32]; 5446e15678aSNathan Whitehorn char newfs[255]; 5452118f387SNathan Whitehorn intmax_t idx; 54650e24496SAlfonso S. Siciliano int hadlabel, choice, nitems; 5472118f387SNathan Whitehorn unsigned i; 54850e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 5492118f387SNathan Whitehorn 55050e24496SAlfonso S. Siciliano struct bsddialog_formitem items[] = { 55150e24496SAlfonso S. Siciliano { "Type:", 1, 1, "", 1, 12, 12, 15, NULL, 0, 55250e24496SAlfonso S. Siciliano "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, " 55350e24496SAlfonso S. Siciliano "freebsd-swap)"}, 55450e24496SAlfonso S. Siciliano { "Size:", 2, 1, "", 2, 12, 12, 15, NULL, 0, 55550e24496SAlfonso S. Siciliano "Partition size. Append K, M, G for kilobytes, " 55650e24496SAlfonso S. Siciliano "megabytes or gigabytes."}, 55750e24496SAlfonso S. Siciliano { "Mountpoint:", 3, 1, "", 3, 12, 12, 15, NULL, 0, 55850e24496SAlfonso S. Siciliano "Path at which to mount this partition (leave blank " 55950e24496SAlfonso S. Siciliano "for swap, set to / for root filesystem)"}, 56050e24496SAlfonso S. Siciliano { "Label:", 4, 1, "", 4, 12, 12, 15, NULL, 0, 56150e24496SAlfonso S. Siciliano "Partition name. Not all partition schemes support this."}, 5622118f387SNathan Whitehorn }; 5632118f387SNathan Whitehorn 56450e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 56550e24496SAlfonso S. Siciliano 5662118f387SNathan Whitehorn /* 5672118f387SNathan Whitehorn * Find the PART geom we are manipulating. This may be a consumer of 5682118f387SNathan Whitehorn * this provider, or its parent. Check the consumer case first. 5692118f387SNathan Whitehorn */ 5702118f387SNathan Whitehorn geom = NULL; 5712118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 5722118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 573f36a5e0fSNathan Whitehorn /* Check for zombie geoms, treating them as blank */ 574f36a5e0fSNathan Whitehorn scheme = NULL; 575f36a5e0fSNathan Whitehorn LIST_FOREACH(gc, &cp->lg_geom->lg_config, lg_config) { 576f36a5e0fSNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 577f36a5e0fSNathan Whitehorn scheme = gc->lg_val; 578f36a5e0fSNathan Whitehorn break; 579f36a5e0fSNathan Whitehorn } 580f36a5e0fSNathan Whitehorn } 581f36a5e0fSNathan Whitehorn if (scheme == NULL || strcmp(scheme, "(none)") == 0) { 582f36a5e0fSNathan Whitehorn gpart_partition(cp->lg_geom->lg_name, NULL); 5832118f387SNathan Whitehorn return; 584f36a5e0fSNathan Whitehorn } 5852118f387SNathan Whitehorn 586987415b1SNathan Whitehorn /* If this is a nested partition, edit as usual */ 587987415b1SNathan Whitehorn if (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 588987415b1SNathan Whitehorn break; 589987415b1SNathan Whitehorn 5902118f387SNathan Whitehorn /* Destroy the geom and all sub-partitions */ 591f36a5e0fSNathan Whitehorn gpart_destroy(cp->lg_geom); 5922118f387SNathan Whitehorn 5932118f387SNathan Whitehorn /* Now re-partition and return */ 5942118f387SNathan Whitehorn gpart_partition(cp->lg_geom->lg_name, NULL); 5952118f387SNathan Whitehorn return; 5962118f387SNathan Whitehorn } 5972118f387SNathan Whitehorn 5982118f387SNathan Whitehorn if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 5992118f387SNathan Whitehorn geom = pp->lg_geom; 6002118f387SNathan Whitehorn 6012118f387SNathan Whitehorn if (geom == NULL) { 6022118f387SNathan Whitehorn /* Disk not partitioned, so partition it */ 603bcc25b7eSNathan Whitehorn gpart_partition(pp->lg_name, NULL); 6042118f387SNathan Whitehorn return; 6052118f387SNathan Whitehorn } 6062118f387SNathan Whitehorn 6072118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) { 6082118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 6092118f387SNathan Whitehorn scheme = gc->lg_val; 6102118f387SNathan Whitehorn break; 6112118f387SNathan Whitehorn } 6122118f387SNathan Whitehorn } 6132118f387SNathan Whitehorn 614c67f41d0SNathan Whitehorn nitems = scheme_supports_labels(scheme) ? 4 : 3; 6152118f387SNathan Whitehorn 6162118f387SNathan Whitehorn /* Edit editable parameters of a partition */ 6172118f387SNathan Whitehorn hadlabel = 0; 6182118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 6192118f387SNathan Whitehorn if (strcmp(gc->lg_name, "type") == 0) { 6202118f387SNathan Whitehorn oldtype = gc->lg_val; 62150e24496SAlfonso S. Siciliano items[0].init = gc->lg_val; 6222118f387SNathan Whitehorn } 6232118f387SNathan Whitehorn if (strcmp(gc->lg_name, "label") == 0 && gc->lg_val != NULL) { 6242118f387SNathan Whitehorn hadlabel = 1; 62550e24496SAlfonso S. Siciliano items[3].init = gc->lg_val; 6262118f387SNathan Whitehorn } 6272118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) 6282118f387SNathan Whitehorn idx = atoi(gc->lg_val); 6292118f387SNathan Whitehorn } 6302118f387SNathan Whitehorn 6312118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 6322118f387SNathan Whitehorn if (md->name != NULL && strcmp(md->name, pp->lg_name) == 0) { 6332118f387SNathan Whitehorn if (md->fstab != NULL) 63450e24496SAlfonso S. Siciliano items[2].init = md->fstab->fs_file; 6352118f387SNathan Whitehorn break; 6362118f387SNathan Whitehorn } 6372118f387SNathan Whitehorn } 6382118f387SNathan Whitehorn 6392118f387SNathan Whitehorn humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE, 6402118f387SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 64150e24496SAlfonso S. Siciliano items[1].init = sizestr; 6422118f387SNathan Whitehorn 6432118f387SNathan Whitehorn editpart: 64450e24496SAlfonso S. Siciliano conf.form.value_without_ok = true; 64550e24496SAlfonso S. Siciliano conf.title = "Edit Partition"; 64650e24496SAlfonso S. Siciliano choice = bsddialog_form(&conf, "", 0, 0, 0, nitems, items); 6472118f387SNathan Whitehorn 64850e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 649987415b1SNathan Whitehorn goto endedit; 6502118f387SNathan Whitehorn 651e24e98d0SWojciech Macek /* If this is the root partition, check that this fs is bootable */ 65250e24496SAlfonso S. Siciliano if (strcmp(items[2].value, "/") == 0 && !is_fs_bootable(scheme, 65350e24496SAlfonso S. Siciliano items[0].value)) { 654e24e98d0SWojciech Macek char message[512]; 655e24e98d0SWojciech Macek sprintf(message, "This file system (%s) is not bootable " 656e24e98d0SWojciech Macek "on this system. Are you sure you want to proceed?", 65750e24496SAlfonso S. Siciliano items[0].value); 65850e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 65950e24496SAlfonso S. Siciliano conf.title = "Warning"; 66050e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, message, 0, 0); 66150e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 66250e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 663e24e98d0SWojciech Macek goto editpart; 664e24e98d0SWojciech Macek } 665e24e98d0SWojciech Macek 6662118f387SNathan Whitehorn /* Check if the label has a / in it */ 66750e24496SAlfonso S. Siciliano if (items[3].value != NULL && strchr(items[3].value, '/') != NULL) { 66850e24496SAlfonso S. Siciliano conf.title = "Error"; 66950e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "Label contains a /, which is not an " 67050e24496SAlfonso S. Siciliano "allowed character.", 0, 0); 6712118f387SNathan Whitehorn goto editpart; 6722118f387SNathan Whitehorn } 6732118f387SNathan Whitehorn 6742118f387SNathan Whitehorn r = gctl_get_handle(); 6752118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 6762118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 6772118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 6782118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "modify"); 6792118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 68050e24496SAlfonso S. Siciliano if (items[3].value != NULL && (hadlabel || items[3].value[0] != '\0')) 68150e24496SAlfonso S. Siciliano gctl_ro_param(r, "label", -1, items[3].value); 68250e24496SAlfonso S. Siciliano gctl_ro_param(r, "type", -1, items[0].value); 6832118f387SNathan Whitehorn errstr = gctl_issue(r); 6842118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 6852118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 6862118f387SNathan Whitehorn gctl_free(r); 6872118f387SNathan Whitehorn goto editpart; 6882118f387SNathan Whitehorn } 6892118f387SNathan Whitehorn gctl_free(r); 6902118f387SNathan Whitehorn 69150e24496SAlfonso S. Siciliano newfs_command(items[0].value, newfs, 1); 69250e24496SAlfonso S. Siciliano set_default_part_metadata(pp->lg_name, scheme, items[0].value, 69350e24496SAlfonso S. Siciliano items[2].value, (strcmp(oldtype, items[0].value) != 0) ? 69450de5d07SNathan Whitehorn newfs : NULL); 6952118f387SNathan Whitehorn 696987415b1SNathan Whitehorn endedit: 69750e24496SAlfonso S. Siciliano if (strcmp(oldtype, items[0].value) != 0 && cp != NULL) 698987415b1SNathan Whitehorn gpart_destroy(cp->lg_geom); 69950e24496SAlfonso S. Siciliano if (strcmp(oldtype, items[0].value) != 0 && strcmp(items[0].value, 700987415b1SNathan Whitehorn "freebsd") == 0) 701987415b1SNathan Whitehorn gpart_partition(pp->lg_name, "BSD"); 702987415b1SNathan Whitehorn 70363128851SMarcelo Araujo for (i = 0; i < nitems(items); i++) 70450e24496SAlfonso S. Siciliano if (items[i].value != NULL) 70550e24496SAlfonso S. Siciliano free(items[i].value); 7062118f387SNathan Whitehorn } 7072118f387SNathan Whitehorn 7082118f387SNathan Whitehorn void 7092118f387SNathan Whitehorn set_default_part_metadata(const char *name, const char *scheme, 71050de5d07SNathan Whitehorn const char *type, const char *mountpoint, const char *newfs) 7112118f387SNathan Whitehorn { 7122118f387SNathan Whitehorn struct partition_metadata *md; 7136e15678aSNathan Whitehorn char *zpool_name = NULL; 71452f39da1SNathan Whitehorn const char *default_bootmount = NULL; 7156e15678aSNathan Whitehorn int i; 7162118f387SNathan Whitehorn 7172118f387SNathan Whitehorn /* Set part metadata */ 7182118f387SNathan Whitehorn md = get_part_metadata(name, 1); 7192118f387SNathan Whitehorn 7202118f387SNathan Whitehorn if (newfs) { 7212118f387SNathan Whitehorn if (md->newfs != NULL) { 7222118f387SNathan Whitehorn free(md->newfs); 7232118f387SNathan Whitehorn md->newfs = NULL; 7242118f387SNathan Whitehorn } 7252118f387SNathan Whitehorn 72650de5d07SNathan Whitehorn if (newfs != NULL && newfs[0] != '\0') { 72750de5d07SNathan Whitehorn md->newfs = malloc(strlen(newfs) + strlen(" /dev/") + 7286e15678aSNathan Whitehorn strlen(mountpoint) + 5 + strlen(name) + 1); 7296e15678aSNathan Whitehorn if (strcmp("freebsd-zfs", type) == 0) { 7306e15678aSNathan Whitehorn zpool_name = strdup((strlen(mountpoint) == 1) ? 7316e15678aSNathan Whitehorn "root" : &mountpoint[1]); 7326e15678aSNathan Whitehorn for (i = 0; zpool_name[i] != 0; i++) 7336e15678aSNathan Whitehorn if (!isalnum(zpool_name[i])) 7346e15678aSNathan Whitehorn zpool_name[i] = '_'; 7356e15678aSNathan Whitehorn sprintf(md->newfs, "%s %s /dev/%s", newfs, 7366e15678aSNathan Whitehorn zpool_name, name); 7376e15678aSNathan Whitehorn } else { 73850de5d07SNathan Whitehorn sprintf(md->newfs, "%s /dev/%s", newfs, name); 7392118f387SNathan Whitehorn } 7402118f387SNathan Whitehorn } 7416e15678aSNathan Whitehorn } 7422118f387SNathan Whitehorn 7432118f387SNathan Whitehorn if (strcmp(type, "freebsd-swap") == 0) 7442118f387SNathan Whitehorn mountpoint = "none"; 74552f39da1SNathan Whitehorn if (strcmp(type, bootpart_type(scheme, &default_bootmount)) == 0) { 7460b7472b3SNathan Whitehorn if (default_bootmount == NULL) 7472118f387SNathan Whitehorn md->bootcode = 1; 74852f39da1SNathan Whitehorn else if (mountpoint == NULL || strlen(mountpoint) == 0) 74952f39da1SNathan Whitehorn mountpoint = default_bootmount; 75052f39da1SNathan Whitehorn } 7512118f387SNathan Whitehorn 7522118f387SNathan Whitehorn if (mountpoint == NULL || mountpoint[0] == '\0') { 7532118f387SNathan Whitehorn if (md->fstab != NULL) { 7542118f387SNathan Whitehorn free(md->fstab->fs_spec); 7552118f387SNathan Whitehorn free(md->fstab->fs_file); 7562118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 7572118f387SNathan Whitehorn free(md->fstab->fs_mntops); 7582118f387SNathan Whitehorn free(md->fstab->fs_type); 7592118f387SNathan Whitehorn free(md->fstab); 7602118f387SNathan Whitehorn md->fstab = NULL; 7612118f387SNathan Whitehorn } 7622118f387SNathan Whitehorn } else { 7632118f387SNathan Whitehorn if (md->fstab == NULL) { 7642118f387SNathan Whitehorn md->fstab = malloc(sizeof(struct fstab)); 7652118f387SNathan Whitehorn } else { 7662118f387SNathan Whitehorn free(md->fstab->fs_spec); 7672118f387SNathan Whitehorn free(md->fstab->fs_file); 7682118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 7692118f387SNathan Whitehorn free(md->fstab->fs_mntops); 7702118f387SNathan Whitehorn free(md->fstab->fs_type); 7712118f387SNathan Whitehorn } 7726e15678aSNathan Whitehorn if (strcmp("freebsd-zfs", type) == 0) { 7736e15678aSNathan Whitehorn md->fstab->fs_spec = strdup(zpool_name); 7746e15678aSNathan Whitehorn } else { 7756e15678aSNathan Whitehorn md->fstab->fs_spec = malloc(strlen(name) + 7766e15678aSNathan Whitehorn strlen("/dev/") + 1); 7772118f387SNathan Whitehorn sprintf(md->fstab->fs_spec, "/dev/%s", name); 7786e15678aSNathan Whitehorn } 7792118f387SNathan Whitehorn md->fstab->fs_file = strdup(mountpoint); 7802118f387SNathan Whitehorn /* Get VFS from text after freebsd-, if possible */ 78150de5d07SNathan Whitehorn if (strncmp("freebsd-", type, 8) == 0) 7822118f387SNathan Whitehorn md->fstab->fs_vfstype = strdup(&type[8]); 7839f7602f0SNathan Whitehorn else if (strcmp("fat32", type) == 0 || strcmp("efi", type) == 0 7849f7602f0SNathan Whitehorn || strcmp("ms-basic-data", type) == 0) 78550de5d07SNathan Whitehorn md->fstab->fs_vfstype = strdup("msdosfs"); 7862118f387SNathan Whitehorn else 7872118f387SNathan Whitehorn md->fstab->fs_vfstype = strdup(type); /* Guess */ 7882118f387SNathan Whitehorn if (strcmp(type, "freebsd-swap") == 0) { 7892118f387SNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_SW); 7902118f387SNathan Whitehorn md->fstab->fs_freq = 0; 7912118f387SNathan Whitehorn md->fstab->fs_passno = 0; 7926e15678aSNathan Whitehorn } else if (strcmp(type, "freebsd-zfs") == 0) { 7936e15678aSNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_RW); 7946e15678aSNathan Whitehorn md->fstab->fs_freq = 0; 7956e15678aSNathan Whitehorn md->fstab->fs_passno = 0; 7962118f387SNathan Whitehorn } else { 7972118f387SNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_RW); 7982118f387SNathan Whitehorn if (strcmp(mountpoint, "/") == 0) { 7992118f387SNathan Whitehorn md->fstab->fs_freq = 1; 8002118f387SNathan Whitehorn md->fstab->fs_passno = 1; 8012118f387SNathan Whitehorn } else { 8022118f387SNathan Whitehorn md->fstab->fs_freq = 2; 8032118f387SNathan Whitehorn md->fstab->fs_passno = 2; 8042118f387SNathan Whitehorn } 8052118f387SNathan Whitehorn } 8062118f387SNathan Whitehorn md->fstab->fs_mntops = strdup(md->fstab->fs_type); 8072118f387SNathan Whitehorn } 8086e15678aSNathan Whitehorn 8096e15678aSNathan Whitehorn if (zpool_name != NULL) 8106e15678aSNathan Whitehorn free(zpool_name); 8112118f387SNathan Whitehorn } 8122118f387SNathan Whitehorn 8132118f387SNathan Whitehorn static 8142118f387SNathan Whitehorn int part_compare(const void *xa, const void *xb) 8152118f387SNathan Whitehorn { 8162118f387SNathan Whitehorn struct gprovider **a = (struct gprovider **)xa; 8172118f387SNathan Whitehorn struct gprovider **b = (struct gprovider **)xb; 8182118f387SNathan Whitehorn intmax_t astart, bstart; 8192118f387SNathan Whitehorn struct gconfig *gc; 8202118f387SNathan Whitehorn 8212118f387SNathan Whitehorn astart = bstart = 0; 8222118f387SNathan Whitehorn LIST_FOREACH(gc, &(*a)->lg_config, lg_config) 8232118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) { 8242118f387SNathan Whitehorn astart = strtoimax(gc->lg_val, NULL, 0); 8252118f387SNathan Whitehorn break; 8262118f387SNathan Whitehorn } 8272118f387SNathan Whitehorn LIST_FOREACH(gc, &(*b)->lg_config, lg_config) 8282118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) { 8292118f387SNathan Whitehorn bstart = strtoimax(gc->lg_val, NULL, 0); 8302118f387SNathan Whitehorn break; 8312118f387SNathan Whitehorn } 8322118f387SNathan Whitehorn 8332118f387SNathan Whitehorn if (astart < bstart) 8342118f387SNathan Whitehorn return -1; 8352118f387SNathan Whitehorn else if (astart > bstart) 8362118f387SNathan Whitehorn return 1; 8372118f387SNathan Whitehorn else 8382118f387SNathan Whitehorn return 0; 8392118f387SNathan Whitehorn } 8402118f387SNathan Whitehorn 8412118f387SNathan Whitehorn intmax_t 8422118f387SNathan Whitehorn gpart_max_free(struct ggeom *geom, intmax_t *npartstart) 8432118f387SNathan Whitehorn { 8442118f387SNathan Whitehorn struct gconfig *gc; 8452118f387SNathan Whitehorn struct gprovider *pp, **providers; 84647ead00dSDag-Erling Smørgrav intmax_t sectorsize, stripesize, offset; 8472118f387SNathan Whitehorn intmax_t lastend; 8482118f387SNathan Whitehorn intmax_t start, end; 8492118f387SNathan Whitehorn intmax_t maxsize, maxstart; 8502118f387SNathan Whitehorn intmax_t partstart, partend; 8512118f387SNathan Whitehorn int i, nparts; 8522118f387SNathan Whitehorn 8532118f387SNathan Whitehorn /* Now get the maximum free size and free start */ 8542118f387SNathan Whitehorn start = end = 0; 8552118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) { 8562118f387SNathan Whitehorn if (strcmp(gc->lg_name, "first") == 0) 8572118f387SNathan Whitehorn start = strtoimax(gc->lg_val, NULL, 0); 8582118f387SNathan Whitehorn if (strcmp(gc->lg_name, "last") == 0) 8592118f387SNathan Whitehorn end = strtoimax(gc->lg_val, NULL, 0); 8602118f387SNathan Whitehorn } 8612118f387SNathan Whitehorn 8622118f387SNathan Whitehorn i = nparts = 0; 8632118f387SNathan Whitehorn LIST_FOREACH(pp, &geom->lg_provider, lg_provider) 8642118f387SNathan Whitehorn nparts++; 8652118f387SNathan Whitehorn providers = calloc(nparts, sizeof(providers[0])); 8662118f387SNathan Whitehorn LIST_FOREACH(pp, &geom->lg_provider, lg_provider) 8672118f387SNathan Whitehorn providers[i++] = pp; 8682118f387SNathan Whitehorn qsort(providers, nparts, sizeof(providers[0]), part_compare); 8692118f387SNathan Whitehorn 8702118f387SNathan Whitehorn lastend = start - 1; 8712118f387SNathan Whitehorn maxsize = 0; 8722118f387SNathan Whitehorn for (i = 0; i < nparts; i++) { 8732118f387SNathan Whitehorn pp = providers[i]; 8742118f387SNathan Whitehorn 8752118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 8762118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) 8772118f387SNathan Whitehorn partstart = strtoimax(gc->lg_val, NULL, 0); 8782118f387SNathan Whitehorn if (strcmp(gc->lg_name, "end") == 0) 8792118f387SNathan Whitehorn partend = strtoimax(gc->lg_val, NULL, 0); 8802118f387SNathan Whitehorn } 8812118f387SNathan Whitehorn 8822118f387SNathan Whitehorn if (partstart - lastend > maxsize) { 8832118f387SNathan Whitehorn maxsize = partstart - lastend - 1; 8842118f387SNathan Whitehorn maxstart = lastend + 1; 8852118f387SNathan Whitehorn } 8862118f387SNathan Whitehorn 8872118f387SNathan Whitehorn lastend = partend; 8882118f387SNathan Whitehorn } 8892118f387SNathan Whitehorn 8902118f387SNathan Whitehorn if (end - lastend > maxsize) { 8918c7de243SNathan Whitehorn maxsize = end - lastend; 8922118f387SNathan Whitehorn maxstart = lastend + 1; 8932118f387SNathan Whitehorn } 8942118f387SNathan Whitehorn 8952118f387SNathan Whitehorn pp = LIST_FIRST(&geom->lg_consumer)->lg_provider; 8962118f387SNathan Whitehorn 89747ead00dSDag-Erling Smørgrav /* 89847ead00dSDag-Erling Smørgrav * Round the start and size of the largest available space up to 89947ead00dSDag-Erling Smørgrav * the nearest multiple of the adjusted stripe size. 90047ead00dSDag-Erling Smørgrav * 90147ead00dSDag-Erling Smørgrav * The adjusted stripe size is the least common multiple of the 90247ead00dSDag-Erling Smørgrav * actual stripe size, or the sector size if no stripe size was 90347ead00dSDag-Erling Smørgrav * reported, and 4096. The reason for this is that contemporary 90447ead00dSDag-Erling Smørgrav * disks often have 4096-byte physical sectors but report 512 90547ead00dSDag-Erling Smørgrav * bytes instead for compatibility with older / broken operating 90647ead00dSDag-Erling Smørgrav * systems and BIOSes. For the same reasons, virtualized storage 90747ead00dSDag-Erling Smørgrav * may also report a 512-byte stripe size, or none at all. 90847ead00dSDag-Erling Smørgrav */ 90947ead00dSDag-Erling Smørgrav sectorsize = pp->lg_sectorsize; 91047ead00dSDag-Erling Smørgrav if ((stripesize = pp->lg_stripesize) == 0) 91147ead00dSDag-Erling Smørgrav stripesize = sectorsize; 91247ead00dSDag-Erling Smørgrav while (stripesize % 4096 != 0) 91347ead00dSDag-Erling Smørgrav stripesize *= 2; 91447ead00dSDag-Erling Smørgrav if ((offset = maxstart * sectorsize % stripesize) != 0) { 91547ead00dSDag-Erling Smørgrav offset = (stripesize - offset) / sectorsize; 9162118f387SNathan Whitehorn maxstart += offset; 9172118f387SNathan Whitehorn maxsize -= offset; 9182118f387SNathan Whitehorn } 9192118f387SNathan Whitehorn 9202118f387SNathan Whitehorn if (npartstart != NULL) 9212118f387SNathan Whitehorn *npartstart = maxstart; 9222118f387SNathan Whitehorn 9232118f387SNathan Whitehorn return (maxsize); 9242118f387SNathan Whitehorn } 9252118f387SNathan Whitehorn 92652f39da1SNathan Whitehorn static size_t 92752f39da1SNathan Whitehorn add_boot_partition(struct ggeom *geom, struct gprovider *pp, 92852f39da1SNathan Whitehorn const char *scheme, int interactive) 92952f39da1SNathan Whitehorn { 93052f39da1SNathan Whitehorn struct gconfig *gc; 93152f39da1SNathan Whitehorn struct gprovider *ppi; 93252f39da1SNathan Whitehorn int choice; 93350e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 93452f39da1SNathan Whitehorn 93552f39da1SNathan Whitehorn /* Check for existing freebsd-boot partition */ 93652f39da1SNathan Whitehorn LIST_FOREACH(ppi, &geom->lg_provider, lg_provider) { 93752f39da1SNathan Whitehorn struct partition_metadata *md; 93852f39da1SNathan Whitehorn const char *bootmount = NULL; 93952f39da1SNathan Whitehorn 94052f39da1SNathan Whitehorn LIST_FOREACH(gc, &ppi->lg_config, lg_config) 94152f39da1SNathan Whitehorn if (strcmp(gc->lg_name, "type") == 0) 94252f39da1SNathan Whitehorn break; 94352f39da1SNathan Whitehorn if (gc == NULL) 94452f39da1SNathan Whitehorn continue; 94552f39da1SNathan Whitehorn if (strcmp(gc->lg_val, bootpart_type(scheme, &bootmount)) != 0) 94652f39da1SNathan Whitehorn continue; 94752f39da1SNathan Whitehorn 94852f39da1SNathan Whitehorn /* 94952f39da1SNathan Whitehorn * If the boot partition is not mountable and needs partcode, 95052f39da1SNathan Whitehorn * but doesn't have it, it doesn't satisfy our requirements. 95152f39da1SNathan Whitehorn */ 95252f39da1SNathan Whitehorn md = get_part_metadata(ppi->lg_name, 0); 95352f39da1SNathan Whitehorn if (bootmount == NULL && (md == NULL || !md->bootcode)) 95452f39da1SNathan Whitehorn continue; 95552f39da1SNathan Whitehorn 95652f39da1SNathan Whitehorn /* If it is mountable, but mounted somewhere else, remount */ 95752f39da1SNathan Whitehorn if (bootmount != NULL && md != NULL && md->fstab != NULL 95852f39da1SNathan Whitehorn && strlen(md->fstab->fs_file) > 0 95952f39da1SNathan Whitehorn && strcmp(md->fstab->fs_file, bootmount) != 0) 96052f39da1SNathan Whitehorn continue; 96152f39da1SNathan Whitehorn 96252f39da1SNathan Whitehorn /* If it is mountable, but mountpoint is not set, mount it */ 96352f39da1SNathan Whitehorn if (bootmount != NULL && md == NULL) 96452f39da1SNathan Whitehorn set_default_part_metadata(ppi->lg_name, scheme, 96552f39da1SNathan Whitehorn gc->lg_val, bootmount, NULL); 96652f39da1SNathan Whitehorn 96752f39da1SNathan Whitehorn /* Looks good at this point, no added data needed */ 96852f39da1SNathan Whitehorn return (0); 96952f39da1SNathan Whitehorn } 97052f39da1SNathan Whitehorn 97150e24496SAlfonso S. Siciliano if (interactive) { 97250e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 97350e24496SAlfonso S. Siciliano conf.title = "Boot Partition"; 97450e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, 97552f39da1SNathan Whitehorn "This partition scheme requires a boot partition " 97652f39da1SNathan Whitehorn "for the disk to be bootable. Would you like to " 97752f39da1SNathan Whitehorn "make one now?", 0, 0); 97850e24496SAlfonso S. Siciliano } else { 97950e24496SAlfonso S. Siciliano choice = BSDDIALOG_YES; 98050e24496SAlfonso S. Siciliano } 98152f39da1SNathan Whitehorn 98250e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_YES) { 9836134b186SNathan Whitehorn struct partition_metadata *md; 98452f39da1SNathan Whitehorn const char *bootmount = NULL; 9856134b186SNathan Whitehorn char *bootpartname = NULL; 98652f39da1SNathan Whitehorn char sizestr[7]; 98752f39da1SNathan Whitehorn 98852f39da1SNathan Whitehorn humanize_number(sizestr, 7, 98952f39da1SNathan Whitehorn bootpart_size(scheme), "B", HN_AUTOSCALE, 99052f39da1SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 99152f39da1SNathan Whitehorn 99252f39da1SNathan Whitehorn gpart_create(pp, bootpart_type(scheme, &bootmount), 9936134b186SNathan Whitehorn sizestr, bootmount, &bootpartname, 0); 9946134b186SNathan Whitehorn 9956134b186SNathan Whitehorn if (bootpartname == NULL) /* Error reported to user already */ 9966134b186SNathan Whitehorn return 0; 9976134b186SNathan Whitehorn 9986134b186SNathan Whitehorn /* If the part is not mountable, make sure newfs isn't set */ 9996134b186SNathan Whitehorn if (bootmount == NULL) { 10006134b186SNathan Whitehorn md = get_part_metadata(bootpartname, 0); 10016134b186SNathan Whitehorn if (md != NULL && md->newfs != NULL) { 10026134b186SNathan Whitehorn free(md->newfs); 10036134b186SNathan Whitehorn md->newfs = NULL; 10046134b186SNathan Whitehorn } 10056134b186SNathan Whitehorn } 10066134b186SNathan Whitehorn 10076134b186SNathan Whitehorn free(bootpartname); 100852f39da1SNathan Whitehorn 100952f39da1SNathan Whitehorn return (bootpart_size(scheme)); 101052f39da1SNathan Whitehorn } 101152f39da1SNathan Whitehorn 101252f39da1SNathan Whitehorn return (0); 101352f39da1SNathan Whitehorn } 101452f39da1SNathan Whitehorn 10152118f387SNathan Whitehorn void 101652f39da1SNathan Whitehorn gpart_create(struct gprovider *pp, const char *default_type, 101752f39da1SNathan Whitehorn const char *default_size, const char *default_mountpoint, 101852f39da1SNathan Whitehorn char **partname, int interactive) 10192118f387SNathan Whitehorn { 10202118f387SNathan Whitehorn struct gctl_req *r; 10212118f387SNathan Whitehorn struct gconfig *gc; 10222118f387SNathan Whitehorn struct gconsumer *cp; 10232118f387SNathan Whitehorn struct ggeom *geom; 10242118f387SNathan Whitehorn const char *errstr, *scheme; 10257899c6c1SNathan Whitehorn char sizestr[32], startstr[32], output[64], *newpartname; 10266e15678aSNathan Whitehorn char newfs[255], options_fstype[64]; 10272118f387SNathan Whitehorn intmax_t maxsize, size, sector, firstfree, stripe; 10282118f387SNathan Whitehorn uint64_t bytes; 10292118f387SNathan Whitehorn int nitems, choice, junk; 10302118f387SNathan Whitehorn unsigned i; 103150e24496SAlfonso S. Siciliano bool init_allocated; 103250e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 10332118f387SNathan Whitehorn 103450e24496SAlfonso S. Siciliano struct bsddialog_formitem items[] = { 103550e24496SAlfonso S. Siciliano {"Type:", 1, 1, "freebsd-ufs", 1, 12, 12, 15, NULL, 0, 103650e24496SAlfonso S. Siciliano "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, " 103750e24496SAlfonso S. Siciliano "freebsd-swap)"}, 103850e24496SAlfonso S. Siciliano {"Size:", 2, 1, "", 2, 12, 12, 15, NULL, 0, 103950e24496SAlfonso S. Siciliano "Partition size. Append K, M, G for kilobytes, " 104050e24496SAlfonso S. Siciliano "megabytes or gigabytes."}, 104150e24496SAlfonso S. Siciliano {"Mountpoint:", 3, 1, "", 3, 12, 12, 15, NULL, 0, 104250e24496SAlfonso S. Siciliano "Path at which to mount partition (blank for " 104350e24496SAlfonso S. Siciliano "swap, / for root filesystem)"}, 104450e24496SAlfonso S. Siciliano {"Label:", 4, 1, "", 4, 12, 12, 15, NULL, 0, 104550e24496SAlfonso S. Siciliano "Partition name. Not all partition schemes support this."}, 10462118f387SNathan Whitehorn }; 10472118f387SNathan Whitehorn 104850e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 104950e24496SAlfonso S. Siciliano 10502118f387SNathan Whitehorn if (partname != NULL) 10512118f387SNathan Whitehorn *partname = NULL; 10522118f387SNathan Whitehorn 10532118f387SNathan Whitehorn /* Record sector and stripe sizes */ 10542118f387SNathan Whitehorn sector = pp->lg_sectorsize; 10552118f387SNathan Whitehorn stripe = pp->lg_stripesize; 10562118f387SNathan Whitehorn 10572118f387SNathan Whitehorn /* 10582118f387SNathan Whitehorn * Find the PART geom we are manipulating. This may be a consumer of 10592118f387SNathan Whitehorn * this provider, or its parent. Check the consumer case first. 10602118f387SNathan Whitehorn */ 10612118f387SNathan Whitehorn geom = NULL; 10622118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 10632118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 10642118f387SNathan Whitehorn geom = cp->lg_geom; 10652118f387SNathan Whitehorn break; 10662118f387SNathan Whitehorn } 10672118f387SNathan Whitehorn 10682118f387SNathan Whitehorn if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 10692118f387SNathan Whitehorn geom = pp->lg_geom; 10702118f387SNathan Whitehorn 10712118f387SNathan Whitehorn /* Now get the partition scheme */ 10722118f387SNathan Whitehorn scheme = NULL; 10732118f387SNathan Whitehorn if (geom != NULL) { 10742118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) 10752118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) 10762118f387SNathan Whitehorn scheme = gc->lg_val; 10772118f387SNathan Whitehorn } 10782118f387SNathan Whitehorn 10792118f387SNathan Whitehorn if (geom == NULL || scheme == NULL || strcmp(scheme, "(none)") == 0) { 108050e24496SAlfonso S. Siciliano if (gpart_partition(pp->lg_name, NULL) == 0) { 108150e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, 10822118f387SNathan Whitehorn "The partition table has been successfully created." 10832118f387SNathan Whitehorn " Please press Create again to create partitions.", 108450e24496SAlfonso S. Siciliano 0, 0); 108550e24496SAlfonso S. Siciliano } 10862118f387SNathan Whitehorn 10872118f387SNathan Whitehorn return; 10882118f387SNathan Whitehorn } 10892118f387SNathan Whitehorn 10902118f387SNathan Whitehorn /* 10912118f387SNathan Whitehorn * If we still don't have a geom, either the user has 10922118f387SNathan Whitehorn * canceled partitioning or there has been an error which has already 10932118f387SNathan Whitehorn * been displayed, so bail. 10942118f387SNathan Whitehorn */ 10952118f387SNathan Whitehorn if (geom == NULL) 10962118f387SNathan Whitehorn return; 10972118f387SNathan Whitehorn 10982118f387SNathan Whitehorn maxsize = size = gpart_max_free(geom, &firstfree); 10992118f387SNathan Whitehorn if (size <= 0) { 110050e24496SAlfonso S. Siciliano conf .title = "Error"; 110150e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "No free space left on device.", 0, 0); 11022118f387SNathan Whitehorn return; 11032118f387SNathan Whitehorn } 11042118f387SNathan Whitehorn 11052118f387SNathan Whitehorn humanize_number(sizestr, 7, size*sector, "B", HN_AUTOSCALE, 11062118f387SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 110750e24496SAlfonso S. Siciliano items[1].init = sizestr; 11082118f387SNathan Whitehorn 11092118f387SNathan Whitehorn /* Special-case the MBR default type for nested partitions */ 11102b375b4eSYoshihiro Takahashi if (strcmp(scheme, "MBR") == 0) { 111150e24496SAlfonso S. Siciliano items[0].init = "freebsd"; 111250e24496SAlfonso S. Siciliano items[0].bottomdesc = "Filesystem type (e.g. freebsd, fat32)"; 1113bcc25b7eSNathan Whitehorn } 11142118f387SNathan Whitehorn 1115c67f41d0SNathan Whitehorn nitems = scheme_supports_labels(scheme) ? 4 : 3; 11162118f387SNathan Whitehorn 11172118f387SNathan Whitehorn if (default_type != NULL) 111850e24496SAlfonso S. Siciliano items[0].init = (char *)default_type; 11192118f387SNathan Whitehorn if (default_size != NULL) 112050e24496SAlfonso S. Siciliano items[1].init = (char *)default_size; 11212118f387SNathan Whitehorn if (default_mountpoint != NULL) 112250e24496SAlfonso S. Siciliano items[2].init = (char *)default_mountpoint; 11232118f387SNathan Whitehorn 112450de5d07SNathan Whitehorn /* Default options */ 112550e24496SAlfonso S. Siciliano strncpy(options_fstype, items[0].init, 112650de5d07SNathan Whitehorn sizeof(options_fstype)); 112750de5d07SNathan Whitehorn newfs_command(options_fstype, newfs, 1); 112850e24496SAlfonso S. Siciliano 112950e24496SAlfonso S. Siciliano init_allocated = false; 11302118f387SNathan Whitehorn addpartform: 11312118f387SNathan Whitehorn if (interactive) { 113250e24496SAlfonso S. Siciliano conf.button.with_extra = true; 113350e24496SAlfonso S. Siciliano conf.button.extra_label = "Options"; 113450e24496SAlfonso S. Siciliano conf.form.value_without_ok = true; 113550e24496SAlfonso S. Siciliano conf.title = "Add Partition"; 113650e24496SAlfonso S. Siciliano choice = bsddialog_form(&conf, "", 0, 0, 0, nitems, items); 113750e24496SAlfonso S. Siciliano conf.button.with_extra = false; 113850e24496SAlfonso S. Siciliano conf.button.extra_label = NULL; 113950e24496SAlfonso S. Siciliano conf.form.value_without_ok = false; 114050de5d07SNathan Whitehorn switch (choice) { 114150e24496SAlfonso S. Siciliano case BSDDIALOG_OK: 114250de5d07SNathan Whitehorn break; 114350e24496SAlfonso S. Siciliano case BSDDIALOG_CANCEL: 11442118f387SNathan Whitehorn return; 114550e24496SAlfonso S. Siciliano case BSDDIALOG_EXTRA: /* Options */ 114650e24496SAlfonso S. Siciliano strncpy(options_fstype, items[0].value, 114750de5d07SNathan Whitehorn sizeof(options_fstype)); 114850de5d07SNathan Whitehorn newfs_command(options_fstype, newfs, 0); 114950e24496SAlfonso S. Siciliano for (i = 0; i < nitems(items); i++) { 115050e24496SAlfonso S. Siciliano if (init_allocated) 115150e24496SAlfonso S. Siciliano free((char*)items[i].init); 115250e24496SAlfonso S. Siciliano items[i].init = items[i].value; 115350e24496SAlfonso S. Siciliano } 115450e24496SAlfonso S. Siciliano init_allocated = true; 115550de5d07SNathan Whitehorn goto addpartform; 115650de5d07SNathan Whitehorn } 11579b4c606bSAlfonso S. Siciliano } else { /* auto partitioning */ 11589b4c606bSAlfonso S. Siciliano items[0].value = strdup(items[0].init); 11599b4c606bSAlfonso S. Siciliano items[1].value = strdup(items[1].init); 11609b4c606bSAlfonso S. Siciliano items[2].value = strdup(items[2].init); 11619b4c606bSAlfonso S. Siciliano if (nitems > 3) 11629b4c606bSAlfonso S. Siciliano items[3].value = strdup(items[3].init); 116350de5d07SNathan Whitehorn } 116450de5d07SNathan Whitehorn 116550de5d07SNathan Whitehorn /* 116650de5d07SNathan Whitehorn * If the user changed the fs type after specifying options, undo 116750de5d07SNathan Whitehorn * their choices in favor of the new filesystem's defaults. 116850de5d07SNathan Whitehorn */ 116950e24496SAlfonso S. Siciliano if (strcmp(options_fstype, items[0].value) != 0) { 117050e24496SAlfonso S. Siciliano strncpy(options_fstype, items[0].value, sizeof(options_fstype)); 117150de5d07SNathan Whitehorn newfs_command(options_fstype, newfs, 1); 11722118f387SNathan Whitehorn } 11732118f387SNathan Whitehorn 11742118f387SNathan Whitehorn size = maxsize; 117550e24496SAlfonso S. Siciliano if (strlen(items[1].value) > 0) { 117650e24496SAlfonso S. Siciliano if (expand_number(items[1].value, &bytes) != 0) { 11772118f387SNathan Whitehorn char error[512]; 11782118f387SNathan Whitehorn 11792118f387SNathan Whitehorn sprintf(error, "Invalid size: %s\n", strerror(errno)); 118050e24496SAlfonso S. Siciliano conf.title = "Error"; 118150e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, error, 0, 0); 11822118f387SNathan Whitehorn goto addpartform; 11832118f387SNathan Whitehorn } 11842118f387SNathan Whitehorn size = MIN((intmax_t)(bytes/sector), maxsize); 11852118f387SNathan Whitehorn } 11862118f387SNathan Whitehorn 11872118f387SNathan Whitehorn /* Check if the label has a / in it */ 118850e24496SAlfonso S. Siciliano if (items[3].value != NULL && strchr(items[3].value, '/') != NULL) { 118950e24496SAlfonso S. Siciliano conf.title = "Error"; 119050e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "Label contains a /, which is not an " 119150e24496SAlfonso S. Siciliano "allowed character.", 0, 0); 11922118f387SNathan Whitehorn goto addpartform; 11932118f387SNathan Whitehorn } 11942118f387SNathan Whitehorn 11952118f387SNathan Whitehorn /* Warn if no mountpoint set */ 119650e24496SAlfonso S. Siciliano if (strcmp(items[0].value, "freebsd-ufs") == 0 && 119750e24496SAlfonso S. Siciliano items[2].value[0] != '/') { 119840f0d8dcSRavi Pokala choice = 0; 119940f0d8dcSRavi Pokala if (interactive) { 120050e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 120150e24496SAlfonso S. Siciliano conf.title = "Warning"; 120250e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, 12032118f387SNathan Whitehorn "This partition does not have a valid mountpoint " 12042118f387SNathan Whitehorn "(for the partition from which you intend to boot the " 12052118f387SNathan Whitehorn "operating system, the mountpoint should be /). Are you " 12062118f387SNathan Whitehorn "sure you want to continue?" 12072118f387SNathan Whitehorn , 0, 0); 120850e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 120940f0d8dcSRavi Pokala } 121050e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 12112118f387SNathan Whitehorn goto addpartform; 12122118f387SNathan Whitehorn } 12132118f387SNathan Whitehorn 1214a780c996SNathan Whitehorn /* 1215a780c996SNathan Whitehorn * Error if this scheme needs nested partitions, this is one, and 1216a780c996SNathan Whitehorn * a mountpoint was set. 1217a780c996SNathan Whitehorn */ 121850e24496SAlfonso S. Siciliano if (strcmp(items[0].value, "freebsd") == 0 && 121950e24496SAlfonso S. Siciliano strlen(items[2].value) > 0) { 122050e24496SAlfonso S. Siciliano conf.title = "Error"; 122150e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "Partitions of type \"freebsd\" are " 1222a780c996SNathan Whitehorn "nested BSD-type partition schemes and cannot have " 1223a780c996SNathan Whitehorn "mountpoints. After creating one, select it and press " 122450e24496SAlfonso S. Siciliano "Create again to add the actual file systems.", 0, 0); 1225a780c996SNathan Whitehorn goto addpartform; 1226a780c996SNathan Whitehorn } 1227a780c996SNathan Whitehorn 12282118f387SNathan Whitehorn /* If this is the root partition, check that this scheme is bootable */ 122950e24496SAlfonso S. Siciliano if (strcmp(items[2].value, "/") == 0 && !is_scheme_bootable(scheme)) { 12302118f387SNathan Whitehorn char message[512]; 12312118f387SNathan Whitehorn sprintf(message, "This partition scheme (%s) is not bootable " 12322118f387SNathan Whitehorn "on this platform. Are you sure you want to proceed?", 12332118f387SNathan Whitehorn scheme); 123450e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 123550e24496SAlfonso S. Siciliano conf.title = "Warning"; 123650e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, message, 0, 0); 123750e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 123850e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 12392118f387SNathan Whitehorn goto addpartform; 12402118f387SNathan Whitehorn } 12412118f387SNathan Whitehorn 12426e15678aSNathan Whitehorn /* If this is the root partition, check that this fs is bootable */ 124350e24496SAlfonso S. Siciliano if (strcmp(items[2].value, "/") == 0 && !is_fs_bootable(scheme, 124450e24496SAlfonso S. Siciliano items[0].value)) { 12456e15678aSNathan Whitehorn char message[512]; 12466e15678aSNathan Whitehorn sprintf(message, "This file system (%s) is not bootable " 12476e15678aSNathan Whitehorn "on this system. Are you sure you want to proceed?", 124850e24496SAlfonso S. Siciliano items[0].value); 124950e24496SAlfonso S. Siciliano conf.button.default_cancel = true; 125050e24496SAlfonso S. Siciliano conf.title = "Warning"; 125150e24496SAlfonso S. Siciliano choice = bsddialog_yesno(&conf, message, 0, 0); 125250e24496SAlfonso S. Siciliano conf.button.default_cancel = false; 125350e24496SAlfonso S. Siciliano if (choice == BSDDIALOG_CANCEL) 12546e15678aSNathan Whitehorn goto addpartform; 12556e15678aSNathan Whitehorn } 12566e15678aSNathan Whitehorn 12572118f387SNathan Whitehorn /* 12582118f387SNathan Whitehorn * If this is the root partition, and we need a boot partition, ask 12592118f387SNathan Whitehorn * the user to add one. 12602118f387SNathan Whitehorn */ 1261a780c996SNathan Whitehorn 126250e24496SAlfonso S. Siciliano if ((strcmp(items[0].value, "freebsd") == 0 || 126350e24496SAlfonso S. Siciliano strcmp(items[2].value, "/") == 0) && bootpart_size(scheme) > 0) { 126452f39da1SNathan Whitehorn size_t bytes = add_boot_partition(geom, pp, scheme, 126552f39da1SNathan Whitehorn interactive); 12662118f387SNathan Whitehorn 12672118f387SNathan Whitehorn /* Now adjust the part we are really adding forward */ 126852f39da1SNathan Whitehorn if (bytes > 0) { 126952f39da1SNathan Whitehorn firstfree += bytes / sector; 127052f39da1SNathan Whitehorn size -= (bytes + stripe)/sector; 12712118f387SNathan Whitehorn if (stripe > 0 && (firstfree*sector % stripe) != 0) 12722118f387SNathan Whitehorn firstfree += (stripe - ((firstfree*sector) % 12732118f387SNathan Whitehorn stripe)) / sector; 12742118f387SNathan Whitehorn } 12752118f387SNathan Whitehorn } 12762118f387SNathan Whitehorn 12772117cdd4SAlexander Motin output[0] = '\0'; 12782117cdd4SAlexander Motin 12792118f387SNathan Whitehorn r = gctl_get_handle(); 12802118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 12812118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 12822118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 12832118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "add"); 128450e24496SAlfonso S. Siciliano 128550e24496SAlfonso S. Siciliano gctl_ro_param(r, "type", -1, items[0].value); 12862118f387SNathan Whitehorn snprintf(sizestr, sizeof(sizestr), "%jd", size); 12872118f387SNathan Whitehorn gctl_ro_param(r, "size", -1, sizestr); 12882118f387SNathan Whitehorn snprintf(startstr, sizeof(startstr), "%jd", firstfree); 12892118f387SNathan Whitehorn gctl_ro_param(r, "start", -1, startstr); 129050e24496SAlfonso S. Siciliano if (items[3].value != NULL && items[3].value[0] != '\0') 129150e24496SAlfonso S. Siciliano gctl_ro_param(r, "label", -1, items[3].value); 12922117cdd4SAlexander Motin gctl_add_param(r, "output", sizeof(output), output, 12932117cdd4SAlexander Motin GCTL_PARAM_WR | GCTL_PARAM_ASCII); 12942118f387SNathan Whitehorn errstr = gctl_issue(r); 12952118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 12962118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 12972118f387SNathan Whitehorn gctl_free(r); 12982118f387SNathan Whitehorn goto addpartform; 12992118f387SNathan Whitehorn } 13007899c6c1SNathan Whitehorn newpartname = strtok(output, " "); 13017899c6c1SNathan Whitehorn gctl_free(r); 13027899c6c1SNathan Whitehorn 13037899c6c1SNathan Whitehorn /* 13047899c6c1SNathan Whitehorn * Try to destroy any geom that gpart picked up already here from 13057899c6c1SNathan Whitehorn * dirty blocks. 13067899c6c1SNathan Whitehorn */ 13077899c6c1SNathan Whitehorn r = gctl_get_handle(); 13087899c6c1SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 13097899c6c1SNathan Whitehorn gctl_ro_param(r, "arg0", -1, newpartname); 13107899c6c1SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 13117899c6c1SNathan Whitehorn junk = 1; 13127899c6c1SNathan Whitehorn gctl_ro_param(r, "force", sizeof(junk), &junk); 13137899c6c1SNathan Whitehorn gctl_ro_param(r, "verb", -1, "destroy"); 13147899c6c1SNathan Whitehorn gctl_issue(r); /* Error usually expected and non-fatal */ 13157899c6c1SNathan Whitehorn gctl_free(r); 13162118f387SNathan Whitehorn 131752f39da1SNathan Whitehorn 131850e24496SAlfonso S. Siciliano if (strcmp(items[0].value, "freebsd") == 0) 13197899c6c1SNathan Whitehorn gpart_partition(newpartname, "BSD"); 13202118f387SNathan Whitehorn else 13217899c6c1SNathan Whitehorn set_default_part_metadata(newpartname, scheme, 132250e24496SAlfonso S. Siciliano items[0].value, items[2].value, newfs); 13232118f387SNathan Whitehorn 132450e24496SAlfonso S. Siciliano for (i = 0; i < nitems(items); i++) { 132550e24496SAlfonso S. Siciliano if (items[i].value != NULL) { 132650e24496SAlfonso S. Siciliano free(items[i].value); 132750e24496SAlfonso S. Siciliano if (init_allocated && items[i].init != NULL) 132850e24496SAlfonso S. Siciliano free((char*)items[i].init); 132950e24496SAlfonso S. Siciliano } 133050e24496SAlfonso S. Siciliano } 13312118f387SNathan Whitehorn 13322118f387SNathan Whitehorn if (partname != NULL) 13337899c6c1SNathan Whitehorn *partname = strdup(newpartname); 13342118f387SNathan Whitehorn } 13352118f387SNathan Whitehorn 13362118f387SNathan Whitehorn void 13372118f387SNathan Whitehorn gpart_delete(struct gprovider *pp) 13382118f387SNathan Whitehorn { 13392118f387SNathan Whitehorn struct gconfig *gc; 13402118f387SNathan Whitehorn struct ggeom *geom; 13412118f387SNathan Whitehorn struct gconsumer *cp; 13422118f387SNathan Whitehorn struct gctl_req *r; 13432118f387SNathan Whitehorn const char *errstr; 13442118f387SNathan Whitehorn intmax_t idx; 1345f36a5e0fSNathan Whitehorn int is_partition; 134650e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 13472118f387SNathan Whitehorn 13482118f387SNathan Whitehorn /* Is it a partition? */ 13492118f387SNathan Whitehorn is_partition = (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0); 13502118f387SNathan Whitehorn 13512118f387SNathan Whitehorn /* Find out if this is the root of a gpart geom */ 13522118f387SNathan Whitehorn geom = NULL; 13532118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 13542118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 13552118f387SNathan Whitehorn geom = cp->lg_geom; 13562118f387SNathan Whitehorn break; 13572118f387SNathan Whitehorn } 13582118f387SNathan Whitehorn 1359f36a5e0fSNathan Whitehorn /* If so, destroy all children */ 13602118f387SNathan Whitehorn if (geom != NULL) { 1361f36a5e0fSNathan Whitehorn gpart_destroy(geom); 1362f36a5e0fSNathan Whitehorn 1363f36a5e0fSNathan Whitehorn /* If this is a partition, revert it, so it can be deleted */ 13642118f387SNathan Whitehorn if (is_partition) { 1365f36a5e0fSNathan Whitehorn r = gctl_get_handle(); 1366f36a5e0fSNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 1367f36a5e0fSNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 1368f36a5e0fSNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 1369f36a5e0fSNathan Whitehorn gctl_issue(r); /* Ignore non-fatal errors */ 1370f36a5e0fSNathan Whitehorn gctl_free(r); 13712118f387SNathan Whitehorn } 13722118f387SNathan Whitehorn } 13732118f387SNathan Whitehorn 13742118f387SNathan Whitehorn /* 13752118f387SNathan Whitehorn * If this is not a partition, see if that is a problem, complain if 13762118f387SNathan Whitehorn * necessary, and return always, since we need not do anything further, 13772118f387SNathan Whitehorn * error or no. 13782118f387SNathan Whitehorn */ 13792118f387SNathan Whitehorn if (!is_partition) { 138050e24496SAlfonso S. Siciliano if (geom == NULL) { 138150e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 138250e24496SAlfonso S. Siciliano conf.title = "Error"; 138350e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, 138450e24496SAlfonso S. Siciliano "Only partitions can be deleted.", 0, 0); 138550e24496SAlfonso S. Siciliano } 13862118f387SNathan Whitehorn return; 13872118f387SNathan Whitehorn } 13882118f387SNathan Whitehorn 13892118f387SNathan Whitehorn r = gctl_get_handle(); 13902118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, pp->lg_geom->lg_class->lg_name); 13912118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); 13922118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 13932118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "delete"); 13942118f387SNathan Whitehorn 13952118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 13962118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 13972118f387SNathan Whitehorn idx = atoi(gc->lg_val); 13982118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 13992118f387SNathan Whitehorn break; 14002118f387SNathan Whitehorn } 14012118f387SNathan Whitehorn } 14022118f387SNathan Whitehorn 14032118f387SNathan Whitehorn errstr = gctl_issue(r); 14042118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 14052118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 14062118f387SNathan Whitehorn gctl_free(r); 14072118f387SNathan Whitehorn return; 14082118f387SNathan Whitehorn } 14092118f387SNathan Whitehorn 14102118f387SNathan Whitehorn gctl_free(r); 14112118f387SNathan Whitehorn 14122118f387SNathan Whitehorn delete_part_metadata(pp->lg_name); 14132118f387SNathan Whitehorn } 14142118f387SNathan Whitehorn 14152118f387SNathan Whitehorn void 14162118f387SNathan Whitehorn gpart_revert_all(struct gmesh *mesh) 14172118f387SNathan Whitehorn { 14182118f387SNathan Whitehorn struct gclass *classp; 14192118f387SNathan Whitehorn struct gconfig *gc; 14202118f387SNathan Whitehorn struct ggeom *gp; 14212118f387SNathan Whitehorn struct gctl_req *r; 14222118f387SNathan Whitehorn const char *modified; 142350e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 14242118f387SNathan Whitehorn 14252118f387SNathan Whitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 14262118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") == 0) 14272118f387SNathan Whitehorn break; 14282118f387SNathan Whitehorn } 14292118f387SNathan Whitehorn 14302118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") != 0) { 143150e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 143250e24496SAlfonso S. Siciliano conf.title = "Error"; 143350e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "gpart not found!", 0, 0); 14342118f387SNathan Whitehorn return; 14352118f387SNathan Whitehorn } 14362118f387SNathan Whitehorn 14372118f387SNathan Whitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 14382118f387SNathan Whitehorn modified = "true"; /* XXX: If we don't know (kernel too old), 14392118f387SNathan Whitehorn * assume there are modifications. */ 14402118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 14412118f387SNathan Whitehorn if (strcmp(gc->lg_name, "modified") == 0) { 14422118f387SNathan Whitehorn modified = gc->lg_val; 14432118f387SNathan Whitehorn break; 14442118f387SNathan Whitehorn } 14452118f387SNathan Whitehorn } 14462118f387SNathan Whitehorn 14472118f387SNathan Whitehorn if (strcmp(modified, "false") == 0) 14482118f387SNathan Whitehorn continue; 14492118f387SNathan Whitehorn 14502118f387SNathan Whitehorn r = gctl_get_handle(); 14512118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 14522118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 14532118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 14542118f387SNathan Whitehorn 14557899c6c1SNathan Whitehorn gctl_issue(r); 14562118f387SNathan Whitehorn gctl_free(r); 14572118f387SNathan Whitehorn } 14582118f387SNathan Whitehorn } 14592118f387SNathan Whitehorn 14602118f387SNathan Whitehorn void 14612118f387SNathan Whitehorn gpart_commit(struct gmesh *mesh) 14622118f387SNathan Whitehorn { 14632118f387SNathan Whitehorn struct partition_metadata *md; 14642118f387SNathan Whitehorn struct gclass *classp; 14652118f387SNathan Whitehorn struct ggeom *gp; 14662118f387SNathan Whitehorn struct gconfig *gc; 14672118f387SNathan Whitehorn struct gconsumer *cp; 14682118f387SNathan Whitehorn struct gprovider *pp; 14692118f387SNathan Whitehorn struct gctl_req *r; 14702118f387SNathan Whitehorn const char *errstr; 14712118f387SNathan Whitehorn const char *modified; 14726e15678aSNathan Whitehorn const char *rootfs; 147350e24496SAlfonso S. Siciliano struct bsddialog_conf conf; 14742118f387SNathan Whitehorn 14752118f387SNathan Whitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 14762118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") == 0) 14772118f387SNathan Whitehorn break; 14782118f387SNathan Whitehorn } 14792118f387SNathan Whitehorn 14806e15678aSNathan Whitehorn /* Figure out what filesystem / uses */ 14816e15678aSNathan Whitehorn rootfs = "ufs"; /* Assume ufs if nothing else present */ 14826e15678aSNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 14836e15678aSNathan Whitehorn if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) { 14846e15678aSNathan Whitehorn rootfs = md->fstab->fs_vfstype; 14856e15678aSNathan Whitehorn break; 14866e15678aSNathan Whitehorn } 14876e15678aSNathan Whitehorn } 14886e15678aSNathan Whitehorn 14892118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") != 0) { 149050e24496SAlfonso S. Siciliano bsddialog_initconf(&conf); 149150e24496SAlfonso S. Siciliano conf.title = "Error"; 149250e24496SAlfonso S. Siciliano bsddialog_msgbox(&conf, "gpart not found!", 0, 0); 14932118f387SNathan Whitehorn return; 14942118f387SNathan Whitehorn } 14952118f387SNathan Whitehorn 14962118f387SNathan Whitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 14972118f387SNathan Whitehorn modified = "true"; /* XXX: If we don't know (kernel too old), 14982118f387SNathan Whitehorn * assume there are modifications. */ 14992118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 15002118f387SNathan Whitehorn if (strcmp(gc->lg_name, "modified") == 0) { 15012118f387SNathan Whitehorn modified = gc->lg_val; 15022118f387SNathan Whitehorn break; 15032118f387SNathan Whitehorn } 15042118f387SNathan Whitehorn } 15052118f387SNathan Whitehorn 15062118f387SNathan Whitehorn if (strcmp(modified, "false") == 0) 15072118f387SNathan Whitehorn continue; 15082118f387SNathan Whitehorn 15092118f387SNathan Whitehorn /* Add bootcode if necessary, before the commit */ 15102118f387SNathan Whitehorn md = get_part_metadata(gp->lg_name, 0); 15112118f387SNathan Whitehorn if (md != NULL && md->bootcode) 15122118f387SNathan Whitehorn gpart_bootcode(gp); 15132118f387SNathan Whitehorn 15142118f387SNathan Whitehorn /* Now install partcode on its partitions, if necessary */ 15152118f387SNathan Whitehorn LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 15162118f387SNathan Whitehorn md = get_part_metadata(pp->lg_name, 0); 15172118f387SNathan Whitehorn if (md == NULL || !md->bootcode) 15182118f387SNathan Whitehorn continue; 15192118f387SNathan Whitehorn 15202118f387SNathan Whitehorn /* Mark this partition active if that's required */ 15212118f387SNathan Whitehorn gpart_activate(pp); 15222118f387SNathan Whitehorn 15232118f387SNathan Whitehorn /* Check if the partition has sub-partitions */ 15242118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 15252118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, 15262118f387SNathan Whitehorn "PART") == 0) 15272118f387SNathan Whitehorn break; 15282118f387SNathan Whitehorn 15292118f387SNathan Whitehorn if (cp == NULL) /* No sub-partitions */ 15306e15678aSNathan Whitehorn gpart_partcode(pp, rootfs); 15312118f387SNathan Whitehorn } 15322118f387SNathan Whitehorn 15332118f387SNathan Whitehorn r = gctl_get_handle(); 15342118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 15352118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 15362118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "commit"); 15372118f387SNathan Whitehorn 15382118f387SNathan Whitehorn errstr = gctl_issue(r); 15392118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 15402118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 15412118f387SNathan Whitehorn gctl_free(r); 15422118f387SNathan Whitehorn } 15432118f387SNathan Whitehorn } 15442118f387SNathan Whitehorn 1545