12118f387SNathan Whitehorn /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31de7b4b8SPedro F. Giffuni * 42118f387SNathan Whitehorn * Copyright (c) 2011 Nathan Whitehorn 52118f387SNathan Whitehorn * All rights reserved. 62118f387SNathan Whitehorn * 72118f387SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 82118f387SNathan Whitehorn * modification, are permitted provided that the following conditions 92118f387SNathan Whitehorn * are met: 102118f387SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 112118f387SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 122118f387SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 132118f387SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 142118f387SNathan Whitehorn * documentation and/or other materials provided with the distribution. 152118f387SNathan Whitehorn * 162118f387SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 172118f387SNathan Whitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 182118f387SNathan Whitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 192118f387SNathan Whitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 202118f387SNathan Whitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 212118f387SNathan Whitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 222118f387SNathan Whitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 232118f387SNathan Whitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 242118f387SNathan Whitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 252118f387SNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 262118f387SNathan Whitehorn * SUCH DAMAGE. 272118f387SNathan Whitehorn * 282118f387SNathan Whitehorn * $FreeBSD$ 292118f387SNathan Whitehorn */ 302118f387SNathan Whitehorn 312118f387SNathan Whitehorn #include <sys/param.h> 326e15678aSNathan Whitehorn #include <sys/stat.h> 332118f387SNathan Whitehorn #include <errno.h> 34*db8b5613SRebecca Cran #include <fcntl.h> 352118f387SNathan Whitehorn #include <libutil.h> 362118f387SNathan Whitehorn #include <inttypes.h> 372118f387SNathan Whitehorn 382118f387SNathan Whitehorn #include <libgeom.h> 392118f387SNathan Whitehorn #include <dialog.h> 402118f387SNathan Whitehorn #include <dlg_keys.h> 412118f387SNathan Whitehorn 422118f387SNathan Whitehorn #include "partedit.h" 432118f387SNathan Whitehorn 442118f387SNathan Whitehorn #define GPART_FLAGS "x" /* Do not commit changes by default */ 452118f387SNathan Whitehorn 462118f387SNathan Whitehorn static void 472118f387SNathan Whitehorn gpart_show_error(const char *title, const char *explanation, const char *errstr) 482118f387SNathan Whitehorn { 492118f387SNathan Whitehorn char *errmsg; 502118f387SNathan Whitehorn char message[512]; 512118f387SNathan Whitehorn int error; 522118f387SNathan Whitehorn 532118f387SNathan Whitehorn if (explanation == NULL) 542118f387SNathan Whitehorn explanation = ""; 552118f387SNathan Whitehorn 562118f387SNathan Whitehorn error = strtol(errstr, &errmsg, 0); 572118f387SNathan Whitehorn if (errmsg != errstr) { 582118f387SNathan Whitehorn while (errmsg[0] == ' ') 592118f387SNathan Whitehorn errmsg++; 602118f387SNathan Whitehorn if (errmsg[0] != '\0') 612118f387SNathan Whitehorn sprintf(message, "%s%s. %s", explanation, 622118f387SNathan Whitehorn strerror(error), errmsg); 632118f387SNathan Whitehorn else 642118f387SNathan Whitehorn sprintf(message, "%s%s", explanation, strerror(error)); 652118f387SNathan Whitehorn } else { 662118f387SNathan Whitehorn sprintf(message, "%s%s", explanation, errmsg); 672118f387SNathan Whitehorn } 682118f387SNathan Whitehorn 692118f387SNathan Whitehorn dialog_msgbox(title, message, 0, 0, TRUE); 702118f387SNathan Whitehorn } 712118f387SNathan Whitehorn 72c67f41d0SNathan Whitehorn static int 73c67f41d0SNathan Whitehorn scheme_supports_labels(const char *scheme) 74c67f41d0SNathan Whitehorn { 75c67f41d0SNathan Whitehorn if (strcmp(scheme, "APM") == 0) 76c67f41d0SNathan Whitehorn return (1); 77c67f41d0SNathan Whitehorn if (strcmp(scheme, "GPT") == 0) 78c67f41d0SNathan Whitehorn return (1); 79c67f41d0SNathan Whitehorn 80c67f41d0SNathan Whitehorn return (0); 81c67f41d0SNathan Whitehorn } 82c67f41d0SNathan Whitehorn 8350de5d07SNathan Whitehorn static void 8450de5d07SNathan Whitehorn newfs_command(const char *fstype, char *command, int use_default) 8550de5d07SNathan Whitehorn { 8650de5d07SNathan Whitehorn if (strcmp(fstype, "freebsd-ufs") == 0) { 8750de5d07SNathan Whitehorn int i; 8850de5d07SNathan Whitehorn DIALOG_LISTITEM items[] = { 8950de5d07SNathan Whitehorn {"UFS1", "UFS Version 1", 9050de5d07SNathan Whitehorn "Use version 1 of the UFS file system instead " 9150de5d07SNathan Whitehorn "of version 2 (not recommended)", 0 }, 9250de5d07SNathan Whitehorn {"SU", "Softupdates", 9350de5d07SNathan Whitehorn "Enable softupdates (default)", 1 }, 9450de5d07SNathan Whitehorn {"SUJ", "Softupdates journaling", 954a8b3e41SEd Maste "Enable file system journaling (default - " 964a8b3e41SEd Maste "turn off for SSDs)", 1 }, 9750de5d07SNathan Whitehorn {"TRIM", "Enable SSD TRIM support", 9850de5d07SNathan Whitehorn "Enable TRIM support, useful on solid-state drives", 9950de5d07SNathan Whitehorn 0 }, 10050de5d07SNathan Whitehorn }; 10150de5d07SNathan Whitehorn 10250de5d07SNathan Whitehorn if (!use_default) { 10350de5d07SNathan Whitehorn int choice; 10450de5d07SNathan Whitehorn choice = dlg_checklist("UFS Options", "", 0, 0, 0, 10563128851SMarcelo Araujo nitems(items), items, NULL, 10650de5d07SNathan Whitehorn FLAG_CHECK, &i); 10750de5d07SNathan Whitehorn if (choice == 1) /* Cancel */ 10850de5d07SNathan Whitehorn return; 10950de5d07SNathan Whitehorn } 11050de5d07SNathan Whitehorn 11150de5d07SNathan Whitehorn strcpy(command, "newfs "); 11263128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 11350de5d07SNathan Whitehorn if (items[i].state == 0) 11450de5d07SNathan Whitehorn continue; 11550de5d07SNathan Whitehorn if (strcmp(items[i].name, "UFS1") == 0) 11650de5d07SNathan Whitehorn strcat(command, "-O1 "); 11750de5d07SNathan Whitehorn else if (strcmp(items[i].name, "SU") == 0) 11850de5d07SNathan Whitehorn strcat(command, "-U "); 11950de5d07SNathan Whitehorn else if (strcmp(items[i].name, "SUJ") == 0) 12050de5d07SNathan Whitehorn strcat(command, "-j "); 12150de5d07SNathan Whitehorn else if (strcmp(items[i].name, "TRIM") == 0) 12250de5d07SNathan Whitehorn strcat(command, "-t "); 12350de5d07SNathan Whitehorn } 1246e15678aSNathan Whitehorn } else if (strcmp(fstype, "freebsd-zfs") == 0) { 1256e15678aSNathan Whitehorn int i; 1266e15678aSNathan Whitehorn DIALOG_LISTITEM items[] = { 1276e15678aSNathan Whitehorn {"fletcher4", "checksum algorithm: fletcher4", 1286e15678aSNathan Whitehorn "Use fletcher4 for data integrity checking. " 1296e15678aSNathan Whitehorn "(default)", 1 }, 1306e15678aSNathan Whitehorn {"fletcher2", "checksum algorithm: fletcher2", 1316e15678aSNathan Whitehorn "Use fletcher2 for data integrity checking. " 1326e15678aSNathan Whitehorn "(not recommended)", 0 }, 1336e15678aSNathan Whitehorn {"sha256", "checksum algorithm: sha256", 1346e15678aSNathan Whitehorn "Use sha256 for data integrity checking. " 1356e15678aSNathan Whitehorn "(not recommended)", 0 }, 1366e15678aSNathan Whitehorn {"atime", "Update atimes for files", 1376e15678aSNathan Whitehorn "Disable atime update", 0 }, 1386e15678aSNathan Whitehorn }; 1396e15678aSNathan Whitehorn 1406e15678aSNathan Whitehorn if (!use_default) { 1416e15678aSNathan Whitehorn int choice; 1426e15678aSNathan Whitehorn choice = dlg_checklist("ZFS Options", "", 0, 0, 0, 14363128851SMarcelo Araujo nitems(items), items, NULL, 1446e15678aSNathan Whitehorn FLAG_CHECK, &i); 1456e15678aSNathan Whitehorn if (choice == 1) /* Cancel */ 1466e15678aSNathan Whitehorn return; 1476e15678aSNathan Whitehorn } 1486e15678aSNathan Whitehorn 1496e15678aSNathan Whitehorn strcpy(command, "zpool create -f -m none "); 1506e15678aSNathan Whitehorn if (getenv("BSDINSTALL_TMPBOOT") != NULL) { 1516e15678aSNathan Whitehorn char zfsboot_path[MAXPATHLEN]; 1526c546e77SConrad Meyer snprintf(zfsboot_path, sizeof(zfsboot_path), "%s/zfs", 1536e15678aSNathan Whitehorn getenv("BSDINSTALL_TMPBOOT")); 1546e15678aSNathan Whitehorn mkdir(zfsboot_path, S_IRWXU | S_IRGRP | S_IXGRP | 1556e15678aSNathan Whitehorn S_IROTH | S_IXOTH); 1566e15678aSNathan Whitehorn sprintf(command, "%s -o cachefile=%s/zpool.cache ", 1576e15678aSNathan Whitehorn command, zfsboot_path); 1586e15678aSNathan Whitehorn } 15963128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 1606e15678aSNathan Whitehorn if (items[i].state == 0) 1616e15678aSNathan Whitehorn continue; 1626e15678aSNathan Whitehorn if (strcmp(items[i].name, "fletcher4") == 0) 1636e15678aSNathan Whitehorn strcat(command, "-O checksum=fletcher4 "); 1646e15678aSNathan Whitehorn else if (strcmp(items[i].name, "fletcher2") == 0) 1656e15678aSNathan Whitehorn strcat(command, "-O checksum=fletcher2 "); 1666e15678aSNathan Whitehorn else if (strcmp(items[i].name, "sha256") == 0) 1676e15678aSNathan Whitehorn strcat(command, "-O checksum=sha256 "); 1686e15678aSNathan Whitehorn else if (strcmp(items[i].name, "atime") == 0) 1696e15678aSNathan Whitehorn strcat(command, "-O atime=off "); 1706e15678aSNathan Whitehorn } 1719f7602f0SNathan Whitehorn } else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0 || 1729f7602f0SNathan Whitehorn strcmp(fstype, "ms-basic-data") == 0) { 17350de5d07SNathan Whitehorn int i; 17450de5d07SNathan Whitehorn DIALOG_LISTITEM items[] = { 17550de5d07SNathan Whitehorn {"FAT32", "FAT Type 32", 17650de5d07SNathan Whitehorn "Create a FAT32 filesystem (default)", 1 }, 17750de5d07SNathan Whitehorn {"FAT16", "FAT Type 16", 17850de5d07SNathan Whitehorn "Create a FAT16 filesystem", 0 }, 17950de5d07SNathan Whitehorn {"FAT12", "FAT Type 12", 18050de5d07SNathan Whitehorn "Create a FAT12 filesystem", 0 }, 18150de5d07SNathan Whitehorn }; 18250de5d07SNathan Whitehorn 18350de5d07SNathan Whitehorn if (!use_default) { 18450de5d07SNathan Whitehorn int choice; 18550de5d07SNathan Whitehorn choice = dlg_checklist("FAT Options", "", 0, 0, 0, 18663128851SMarcelo Araujo nitems(items), items, NULL, 18750de5d07SNathan Whitehorn FLAG_RADIO, &i); 18850de5d07SNathan Whitehorn if (choice == 1) /* Cancel */ 18950de5d07SNathan Whitehorn return; 19050de5d07SNathan Whitehorn } 19150de5d07SNathan Whitehorn 19250de5d07SNathan Whitehorn strcpy(command, "newfs_msdos "); 19363128851SMarcelo Araujo for (i = 0; i < (int)nitems(items); i++) { 19450de5d07SNathan Whitehorn if (items[i].state == 0) 19550de5d07SNathan Whitehorn continue; 196*db8b5613SRebecca Cran if (strcmp(items[i].name, "FAT32") == 0) 197*db8b5613SRebecca Cran strcat(command, "-F 32 -c 1"); 198*db8b5613SRebecca Cran else if (strcmp(items[i].name, "FAT16") == 0) 19950de5d07SNathan Whitehorn strcat(command, "-F 16 "); 200ae2e7abfSNathan Whitehorn else if (strcmp(items[i].name, "FAT12") == 0) 20150de5d07SNathan Whitehorn strcat(command, "-F 12 "); 20250de5d07SNathan Whitehorn } 20350de5d07SNathan Whitehorn } else { 20450de5d07SNathan Whitehorn if (!use_default) 20550de5d07SNathan Whitehorn dialog_msgbox("Error", "No configurable options exist " 20650de5d07SNathan Whitehorn "for this filesystem.", 0, 0, TRUE); 20750de5d07SNathan Whitehorn command[0] = '\0'; 20850de5d07SNathan Whitehorn } 20950de5d07SNathan Whitehorn } 21050de5d07SNathan Whitehorn 2117059fa6fSAllan Jude const char * 2127059fa6fSAllan Jude choose_part_type(const char *def_scheme) 2132118f387SNathan Whitehorn { 2142118f387SNathan Whitehorn int cancel, choice; 2157059fa6fSAllan Jude const char *scheme = NULL; 2162118f387SNathan Whitehorn 2172118f387SNathan Whitehorn DIALOG_LISTITEM items[] = { 2182118f387SNathan Whitehorn {"APM", "Apple Partition Map", 2192118f387SNathan Whitehorn "Bootable on PowerPC Apple Hardware", 0 }, 2202118f387SNathan Whitehorn {"BSD", "BSD Labels", 2212118f387SNathan Whitehorn "Bootable on most x86 systems", 0 }, 2222118f387SNathan Whitehorn {"GPT", "GUID Partition Table", 2230fbcaf76SWojciech Macek "Bootable on most x86 systems and EFI aware ARM64", 0 }, 2242118f387SNathan Whitehorn {"MBR", "DOS Partitions", 2252118f387SNathan Whitehorn "Bootable on most x86 systems", 0 }, 2262118f387SNathan Whitehorn {"VTOC8", "Sun VTOC8 Partition Table", 2272118f387SNathan Whitehorn "Bootable on Sun SPARC systems", 0 }, 2282118f387SNathan Whitehorn }; 2292118f387SNathan Whitehorn 2307059fa6fSAllan Jude parttypemenu: 2317059fa6fSAllan Jude dialog_vars.default_item = __DECONST(char *, def_scheme); 2322118f387SNathan Whitehorn cancel = dlg_menu("Partition Scheme", 2332118f387SNathan Whitehorn "Select a partition scheme for this volume:", 0, 0, 0, 23463128851SMarcelo Araujo nitems(items), items, &choice, NULL); 2352118f387SNathan Whitehorn dialog_vars.default_item = NULL; 2362118f387SNathan Whitehorn 2372118f387SNathan Whitehorn if (cancel) 2387059fa6fSAllan Jude return NULL; 2392118f387SNathan Whitehorn 2402118f387SNathan Whitehorn if (!is_scheme_bootable(items[choice].name)) { 2412118f387SNathan Whitehorn char message[512]; 2422118f387SNathan Whitehorn sprintf(message, "This partition scheme (%s) is not " 2432118f387SNathan Whitehorn "bootable on this platform. Are you sure you want " 2442118f387SNathan Whitehorn "to proceed?", items[choice].name); 2452118f387SNathan Whitehorn dialog_vars.defaultno = TRUE; 2462118f387SNathan Whitehorn cancel = dialog_yesno("Warning", message, 0, 0); 2472118f387SNathan Whitehorn dialog_vars.defaultno = FALSE; 2482118f387SNathan Whitehorn if (cancel) /* cancel */ 2497059fa6fSAllan Jude goto parttypemenu; 2502118f387SNathan Whitehorn } 2512118f387SNathan Whitehorn 2522118f387SNathan Whitehorn scheme = items[choice].name; 2537059fa6fSAllan Jude 2547059fa6fSAllan Jude return scheme; 2557059fa6fSAllan Jude } 2567059fa6fSAllan Jude 2577059fa6fSAllan Jude int 2587059fa6fSAllan Jude gpart_partition(const char *lg_name, const char *scheme) 2597059fa6fSAllan Jude { 2607059fa6fSAllan Jude int cancel; 2617059fa6fSAllan Jude struct gctl_req *r; 2627059fa6fSAllan Jude const char *errstr; 2637059fa6fSAllan Jude 2647059fa6fSAllan Jude schememenu: 2657059fa6fSAllan Jude if (scheme == NULL) { 2667059fa6fSAllan Jude scheme = choose_part_type(default_scheme()); 2677059fa6fSAllan Jude 2687059fa6fSAllan Jude if (scheme == NULL) 2697059fa6fSAllan Jude return (-1); 2707059fa6fSAllan Jude 2717059fa6fSAllan Jude if (!is_scheme_bootable(scheme)) { 2727059fa6fSAllan Jude char message[512]; 2737059fa6fSAllan Jude sprintf(message, "This partition scheme (%s) is not " 2747059fa6fSAllan Jude "bootable on this platform. Are you sure you want " 2757059fa6fSAllan Jude "to proceed?", scheme); 2767059fa6fSAllan Jude dialog_vars.defaultno = TRUE; 2777059fa6fSAllan Jude cancel = dialog_yesno("Warning", message, 0, 0); 2787059fa6fSAllan Jude dialog_vars.defaultno = FALSE; 2797059fa6fSAllan Jude if (cancel) { /* cancel */ 2807059fa6fSAllan Jude /* Reset scheme so user can choose another */ 2817059fa6fSAllan Jude scheme = NULL; 2827059fa6fSAllan Jude goto schememenu; 2837059fa6fSAllan Jude } 2847059fa6fSAllan Jude } 2852118f387SNathan Whitehorn } 2862118f387SNathan Whitehorn 2872118f387SNathan Whitehorn r = gctl_get_handle(); 2882118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 2892118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_name); 2902118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 2912118f387SNathan Whitehorn gctl_ro_param(r, "scheme", -1, scheme); 2922118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "create"); 2932118f387SNathan Whitehorn 2942118f387SNathan Whitehorn errstr = gctl_issue(r); 2952118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 2962118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 2972118f387SNathan Whitehorn gctl_free(r); 2982118f387SNathan Whitehorn scheme = NULL; 2992118f387SNathan Whitehorn goto schememenu; 3002118f387SNathan Whitehorn } 3012118f387SNathan Whitehorn gctl_free(r); 3022118f387SNathan Whitehorn 3032118f387SNathan Whitehorn if (bootcode_path(scheme) != NULL) 3042118f387SNathan Whitehorn get_part_metadata(lg_name, 1)->bootcode = 1; 3052118f387SNathan Whitehorn return (0); 3062118f387SNathan Whitehorn } 3072118f387SNathan Whitehorn 3082118f387SNathan Whitehorn static void 3092118f387SNathan Whitehorn gpart_activate(struct gprovider *pp) 3102118f387SNathan Whitehorn { 3112118f387SNathan Whitehorn struct gconfig *gc; 3122118f387SNathan Whitehorn struct gctl_req *r; 3132118f387SNathan Whitehorn const char *errstr, *scheme; 3142118f387SNathan Whitehorn const char *attribute = NULL; 3152118f387SNathan Whitehorn intmax_t idx; 3162118f387SNathan Whitehorn 3172118f387SNathan Whitehorn /* 3182118f387SNathan Whitehorn * Some partition schemes need this partition to be marked 'active' 3192118f387SNathan Whitehorn * for it to be bootable. 3202118f387SNathan Whitehorn */ 3212118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { 3222118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 3232118f387SNathan Whitehorn scheme = gc->lg_val; 3242118f387SNathan Whitehorn break; 3252118f387SNathan Whitehorn } 3262118f387SNathan Whitehorn } 3272118f387SNathan Whitehorn 3282b375b4eSYoshihiro Takahashi if (strcmp(scheme, "MBR") == 0 || strcmp(scheme, "EBR") == 0) 3292118f387SNathan Whitehorn attribute = "active"; 3302118f387SNathan Whitehorn else 3312118f387SNathan Whitehorn return; 3322118f387SNathan Whitehorn 3332118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 3342118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 3352118f387SNathan Whitehorn idx = atoi(gc->lg_val); 3362118f387SNathan Whitehorn break; 3372118f387SNathan Whitehorn } 3382118f387SNathan Whitehorn } 3392118f387SNathan Whitehorn 3402118f387SNathan Whitehorn r = gctl_get_handle(); 3412118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 3422118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); 3432118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "set"); 3442118f387SNathan Whitehorn gctl_ro_param(r, "attrib", -1, attribute); 3452118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 3462118f387SNathan Whitehorn 3472118f387SNathan Whitehorn errstr = gctl_issue(r); 3482118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 3492118f387SNathan Whitehorn gpart_show_error("Error", "Error marking partition active:", 3502118f387SNathan Whitehorn errstr); 3512118f387SNathan Whitehorn gctl_free(r); 3522118f387SNathan Whitehorn } 3532118f387SNathan Whitehorn 3547059fa6fSAllan Jude void 3557059fa6fSAllan Jude gpart_set_root(const char *lg_name, const char *attribute) 3567059fa6fSAllan Jude { 3577059fa6fSAllan Jude struct gctl_req *r; 3587059fa6fSAllan Jude const char *errstr; 3597059fa6fSAllan Jude 3607059fa6fSAllan Jude r = gctl_get_handle(); 3617059fa6fSAllan Jude gctl_ro_param(r, "class", -1, "PART"); 3627059fa6fSAllan Jude gctl_ro_param(r, "arg0", -1, lg_name); 3637059fa6fSAllan Jude gctl_ro_param(r, "flags", -1, "C"); 3647059fa6fSAllan Jude gctl_ro_param(r, "verb", -1, "set"); 3657059fa6fSAllan Jude gctl_ro_param(r, "attrib", -1, attribute); 3667059fa6fSAllan Jude 3677059fa6fSAllan Jude errstr = gctl_issue(r); 3687059fa6fSAllan Jude if (errstr != NULL && errstr[0] != '\0') 3697059fa6fSAllan Jude gpart_show_error("Error", "Error setting parameter on disk:", 3707059fa6fSAllan Jude errstr); 3717059fa6fSAllan Jude gctl_free(r); 3727059fa6fSAllan Jude } 3737059fa6fSAllan Jude 3742118f387SNathan Whitehorn static void 3752118f387SNathan Whitehorn gpart_bootcode(struct ggeom *gp) 3762118f387SNathan Whitehorn { 3772118f387SNathan Whitehorn const char *bootcode; 3782118f387SNathan Whitehorn struct gconfig *gc; 3792118f387SNathan Whitehorn struct gctl_req *r; 3802118f387SNathan Whitehorn const char *errstr, *scheme; 3812118f387SNathan Whitehorn uint8_t *boot; 3822118f387SNathan Whitehorn size_t bootsize, bytes; 3832118f387SNathan Whitehorn int bootfd; 3842118f387SNathan Whitehorn 3852118f387SNathan Whitehorn /* 3862118f387SNathan Whitehorn * Write default bootcode to the newly partitioned disk, if that 3872118f387SNathan Whitehorn * applies on this platform. 3882118f387SNathan Whitehorn */ 3892118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 3902118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 3912118f387SNathan Whitehorn scheme = gc->lg_val; 3922118f387SNathan Whitehorn break; 3932118f387SNathan Whitehorn } 3942118f387SNathan Whitehorn } 3952118f387SNathan Whitehorn 3962118f387SNathan Whitehorn bootcode = bootcode_path(scheme); 3972118f387SNathan Whitehorn if (bootcode == NULL) 3982118f387SNathan Whitehorn return; 3992118f387SNathan Whitehorn 4002118f387SNathan Whitehorn bootfd = open(bootcode, O_RDONLY); 401c725e3efSKevin Lo if (bootfd < 0) { 4022118f387SNathan Whitehorn dialog_msgbox("Bootcode Error", strerror(errno), 0, 0, 4032118f387SNathan Whitehorn TRUE); 4042118f387SNathan Whitehorn return; 4052118f387SNathan Whitehorn } 4062118f387SNathan Whitehorn 4072118f387SNathan Whitehorn bootsize = lseek(bootfd, 0, SEEK_END); 4082118f387SNathan Whitehorn boot = malloc(bootsize); 4092118f387SNathan Whitehorn lseek(bootfd, 0, SEEK_SET); 4102118f387SNathan Whitehorn bytes = 0; 4112118f387SNathan Whitehorn while (bytes < bootsize) 4122118f387SNathan Whitehorn bytes += read(bootfd, boot + bytes, bootsize - bytes); 4132118f387SNathan Whitehorn close(bootfd); 4142118f387SNathan Whitehorn 4152118f387SNathan Whitehorn r = gctl_get_handle(); 4162118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 4172118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 4182118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "bootcode"); 4192118f387SNathan Whitehorn gctl_ro_param(r, "bootcode", bootsize, boot); 4202118f387SNathan Whitehorn 4212118f387SNathan Whitehorn errstr = gctl_issue(r); 4222118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 4232118f387SNathan Whitehorn gpart_show_error("Bootcode Error", NULL, errstr); 4242118f387SNathan Whitehorn gctl_free(r); 4252118f387SNathan Whitehorn free(boot); 4262118f387SNathan Whitehorn } 4272118f387SNathan Whitehorn 4282118f387SNathan Whitehorn static void 4296e15678aSNathan Whitehorn gpart_partcode(struct gprovider *pp, const char *fstype) 4302118f387SNathan Whitehorn { 4312118f387SNathan Whitehorn struct gconfig *gc; 4322118f387SNathan Whitehorn const char *scheme; 4332118f387SNathan Whitehorn const char *indexstr; 4342118f387SNathan Whitehorn char message[255], command[255]; 4352118f387SNathan Whitehorn 4362118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) { 4372118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 4382118f387SNathan Whitehorn scheme = gc->lg_val; 4392118f387SNathan Whitehorn break; 4402118f387SNathan Whitehorn } 4412118f387SNathan Whitehorn } 4422118f387SNathan Whitehorn 4432118f387SNathan Whitehorn /* Make sure this partition scheme needs partcode on this platform */ 4446e15678aSNathan Whitehorn if (partcode_path(scheme, fstype) == NULL) 4452118f387SNathan Whitehorn return; 4462118f387SNathan Whitehorn 4472118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 4482118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 4492118f387SNathan Whitehorn indexstr = gc->lg_val; 4502118f387SNathan Whitehorn break; 4512118f387SNathan Whitehorn } 4522118f387SNathan Whitehorn } 4532118f387SNathan Whitehorn 4542118f387SNathan Whitehorn /* Shell out to gpart for partcode for now */ 4552118f387SNathan Whitehorn sprintf(command, "gpart bootcode -p %s -i %s %s", 4566e15678aSNathan Whitehorn partcode_path(scheme, fstype), indexstr, pp->lg_geom->lg_name); 4572118f387SNathan Whitehorn if (system(command) != 0) { 4582118f387SNathan Whitehorn sprintf(message, "Error installing partcode on partition %s", 4592118f387SNathan Whitehorn pp->lg_name); 4602118f387SNathan Whitehorn dialog_msgbox("Error", message, 0, 0, TRUE); 4612118f387SNathan Whitehorn } 4622118f387SNathan Whitehorn } 4632118f387SNathan Whitehorn 4642118f387SNathan Whitehorn void 465f36a5e0fSNathan Whitehorn gpart_destroy(struct ggeom *lg_geom) 4662118f387SNathan Whitehorn { 4672118f387SNathan Whitehorn struct gctl_req *r; 468f36a5e0fSNathan Whitehorn struct gprovider *pp; 4692118f387SNathan Whitehorn const char *errstr; 470f36a5e0fSNathan Whitehorn int force = 1; 4712118f387SNathan Whitehorn 472f36a5e0fSNathan Whitehorn /* Delete all child metadata */ 4732118f387SNathan Whitehorn LIST_FOREACH(pp, &lg_geom->lg_provider, lg_provider) 4742118f387SNathan Whitehorn gpart_delete(pp); 4752118f387SNathan Whitehorn 476f36a5e0fSNathan Whitehorn /* Revert any local changes to get this geom into a pristine state */ 477f36a5e0fSNathan Whitehorn r = gctl_get_handle(); 478f36a5e0fSNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 479f36a5e0fSNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); 480f36a5e0fSNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 481f36a5e0fSNathan Whitehorn gctl_issue(r); /* Ignore errors -- these are non-fatal */ 482f36a5e0fSNathan Whitehorn gctl_free(r); 483f36a5e0fSNathan Whitehorn 4842118f387SNathan Whitehorn /* Now destroy the geom itself */ 4852118f387SNathan Whitehorn r = gctl_get_handle(); 4862118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 4872118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, lg_geom->lg_name); 4882118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 489f36a5e0fSNathan Whitehorn gctl_ro_param(r, "force", sizeof(force), &force); 4902118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "destroy"); 4912118f387SNathan Whitehorn errstr = gctl_issue(r); 492987415b1SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 493987415b1SNathan Whitehorn /* 494987415b1SNathan Whitehorn * Check if we reverted away the existence of the geom 495987415b1SNathan Whitehorn * altogether. Show all other errors to the user. 496987415b1SNathan Whitehorn */ 497987415b1SNathan Whitehorn if (strtol(errstr, NULL, 0) != EINVAL) 4982118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 499987415b1SNathan Whitehorn } 5002118f387SNathan Whitehorn gctl_free(r); 5012118f387SNathan Whitehorn 5022118f387SNathan Whitehorn /* And any metadata associated with the partition scheme itself */ 5032118f387SNathan Whitehorn delete_part_metadata(lg_geom->lg_name); 5042118f387SNathan Whitehorn } 5052118f387SNathan Whitehorn 5062118f387SNathan Whitehorn void 5072118f387SNathan Whitehorn gpart_edit(struct gprovider *pp) 5082118f387SNathan Whitehorn { 5092118f387SNathan Whitehorn struct gctl_req *r; 5102118f387SNathan Whitehorn struct gconfig *gc; 5112118f387SNathan Whitehorn struct gconsumer *cp; 5122118f387SNathan Whitehorn struct ggeom *geom; 5132118f387SNathan Whitehorn const char *errstr, *oldtype, *scheme; 5142118f387SNathan Whitehorn struct partition_metadata *md; 5152118f387SNathan Whitehorn char sizestr[32]; 5166e15678aSNathan Whitehorn char newfs[255]; 5172118f387SNathan Whitehorn intmax_t idx; 5182118f387SNathan Whitehorn int hadlabel, choice, junk, nitems; 5192118f387SNathan Whitehorn unsigned i; 5202118f387SNathan Whitehorn 5212118f387SNathan Whitehorn DIALOG_FORMITEM items[] = { 5222118f387SNathan Whitehorn {0, "Type:", 5, 0, 0, FALSE, "", 11, 0, 12, 15, 0, 5236e15678aSNathan Whitehorn FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, " 5246e15678aSNathan Whitehorn "freebsd-swap)", FALSE}, 5252118f387SNathan Whitehorn {0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 0, 0, 5262118f387SNathan Whitehorn FALSE, "Partition size. Append K, M, G for kilobytes, " 5272118f387SNathan Whitehorn "megabytes or gigabytes.", FALSE}, 5282118f387SNathan Whitehorn {0, "Mountpoint:", 11, 2, 0, FALSE, "", 11, 2, 12, 15, 0, 5292118f387SNathan Whitehorn FALSE, "Path at which to mount this partition (leave blank " 5302118f387SNathan Whitehorn "for swap, set to / for root filesystem)", FALSE}, 5312118f387SNathan Whitehorn {0, "Label:", 7, 3, 0, FALSE, "", 11, 3, 12, 15, 0, FALSE, 5322118f387SNathan Whitehorn "Partition name. Not all partition schemes support this.", 5332118f387SNathan Whitehorn FALSE}, 5342118f387SNathan Whitehorn }; 5352118f387SNathan Whitehorn 5362118f387SNathan Whitehorn /* 5372118f387SNathan Whitehorn * Find the PART geom we are manipulating. This may be a consumer of 5382118f387SNathan Whitehorn * this provider, or its parent. Check the consumer case first. 5392118f387SNathan Whitehorn */ 5402118f387SNathan Whitehorn geom = NULL; 5412118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 5422118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 543f36a5e0fSNathan Whitehorn /* Check for zombie geoms, treating them as blank */ 544f36a5e0fSNathan Whitehorn scheme = NULL; 545f36a5e0fSNathan Whitehorn LIST_FOREACH(gc, &cp->lg_geom->lg_config, lg_config) { 546f36a5e0fSNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 547f36a5e0fSNathan Whitehorn scheme = gc->lg_val; 548f36a5e0fSNathan Whitehorn break; 549f36a5e0fSNathan Whitehorn } 550f36a5e0fSNathan Whitehorn } 551f36a5e0fSNathan Whitehorn if (scheme == NULL || strcmp(scheme, "(none)") == 0) { 552f36a5e0fSNathan Whitehorn gpart_partition(cp->lg_geom->lg_name, NULL); 5532118f387SNathan Whitehorn return; 554f36a5e0fSNathan Whitehorn } 5552118f387SNathan Whitehorn 556987415b1SNathan Whitehorn /* If this is a nested partition, edit as usual */ 557987415b1SNathan Whitehorn if (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 558987415b1SNathan Whitehorn break; 559987415b1SNathan Whitehorn 5602118f387SNathan Whitehorn /* Destroy the geom and all sub-partitions */ 561f36a5e0fSNathan Whitehorn gpart_destroy(cp->lg_geom); 5622118f387SNathan Whitehorn 5632118f387SNathan Whitehorn /* Now re-partition and return */ 5642118f387SNathan Whitehorn gpart_partition(cp->lg_geom->lg_name, NULL); 5652118f387SNathan Whitehorn return; 5662118f387SNathan Whitehorn } 5672118f387SNathan Whitehorn 5682118f387SNathan Whitehorn if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 5692118f387SNathan Whitehorn geom = pp->lg_geom; 5702118f387SNathan Whitehorn 5712118f387SNathan Whitehorn if (geom == NULL) { 5722118f387SNathan Whitehorn /* Disk not partitioned, so partition it */ 573bcc25b7eSNathan Whitehorn gpart_partition(pp->lg_name, NULL); 5742118f387SNathan Whitehorn return; 5752118f387SNathan Whitehorn } 5762118f387SNathan Whitehorn 5772118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) { 5782118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) { 5792118f387SNathan Whitehorn scheme = gc->lg_val; 5802118f387SNathan Whitehorn break; 5812118f387SNathan Whitehorn } 5822118f387SNathan Whitehorn } 5832118f387SNathan Whitehorn 584c67f41d0SNathan Whitehorn nitems = scheme_supports_labels(scheme) ? 4 : 3; 5852118f387SNathan Whitehorn 5862118f387SNathan Whitehorn /* Edit editable parameters of a partition */ 5872118f387SNathan Whitehorn hadlabel = 0; 5882118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 5892118f387SNathan Whitehorn if (strcmp(gc->lg_name, "type") == 0) { 5902118f387SNathan Whitehorn oldtype = gc->lg_val; 5912118f387SNathan Whitehorn items[0].text = gc->lg_val; 5922118f387SNathan Whitehorn } 5932118f387SNathan Whitehorn if (strcmp(gc->lg_name, "label") == 0 && gc->lg_val != NULL) { 5942118f387SNathan Whitehorn hadlabel = 1; 5952118f387SNathan Whitehorn items[3].text = gc->lg_val; 5962118f387SNathan Whitehorn } 5972118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) 5982118f387SNathan Whitehorn idx = atoi(gc->lg_val); 5992118f387SNathan Whitehorn } 6002118f387SNathan Whitehorn 6012118f387SNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 6022118f387SNathan Whitehorn if (md->name != NULL && strcmp(md->name, pp->lg_name) == 0) { 6032118f387SNathan Whitehorn if (md->fstab != NULL) 6042118f387SNathan Whitehorn items[2].text = md->fstab->fs_file; 6052118f387SNathan Whitehorn break; 6062118f387SNathan Whitehorn } 6072118f387SNathan Whitehorn } 6082118f387SNathan Whitehorn 6092118f387SNathan Whitehorn humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE, 6102118f387SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 6112118f387SNathan Whitehorn items[1].text = sizestr; 6122118f387SNathan Whitehorn 6132118f387SNathan Whitehorn editpart: 6142118f387SNathan Whitehorn choice = dlg_form("Edit Partition", "", 0, 0, 0, nitems, items, &junk); 6152118f387SNathan Whitehorn 6162118f387SNathan Whitehorn if (choice) /* Cancel pressed */ 617987415b1SNathan Whitehorn goto endedit; 6182118f387SNathan Whitehorn 619e24e98d0SWojciech Macek /* If this is the root partition, check that this fs is bootable */ 620e24e98d0SWojciech Macek if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme, 621e24e98d0SWojciech Macek items[0].text)) { 622e24e98d0SWojciech Macek char message[512]; 623e24e98d0SWojciech Macek sprintf(message, "This file system (%s) is not bootable " 624e24e98d0SWojciech Macek "on this system. Are you sure you want to proceed?", 625e24e98d0SWojciech Macek items[0].text); 626e24e98d0SWojciech Macek dialog_vars.defaultno = TRUE; 627e24e98d0SWojciech Macek choice = dialog_yesno("Warning", message, 0, 0); 628e24e98d0SWojciech Macek dialog_vars.defaultno = FALSE; 629e24e98d0SWojciech Macek if (choice == 1) /* cancel */ 630e24e98d0SWojciech Macek goto editpart; 631e24e98d0SWojciech Macek } 632e24e98d0SWojciech Macek 6332118f387SNathan Whitehorn /* Check if the label has a / in it */ 6342118f387SNathan Whitehorn if (strchr(items[3].text, '/') != NULL) { 6352118f387SNathan Whitehorn dialog_msgbox("Error", "Label contains a /, which is not an " 6362118f387SNathan Whitehorn "allowed character.", 0, 0, TRUE); 6372118f387SNathan Whitehorn goto editpart; 6382118f387SNathan Whitehorn } 6392118f387SNathan Whitehorn 6402118f387SNathan Whitehorn r = gctl_get_handle(); 6412118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 6422118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 6432118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 6442118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "modify"); 6452118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 6462118f387SNathan Whitehorn if (hadlabel || items[3].text[0] != '\0') 6472118f387SNathan Whitehorn gctl_ro_param(r, "label", -1, items[3].text); 6482118f387SNathan Whitehorn gctl_ro_param(r, "type", -1, items[0].text); 6492118f387SNathan Whitehorn errstr = gctl_issue(r); 6502118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 6512118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 6522118f387SNathan Whitehorn gctl_free(r); 6532118f387SNathan Whitehorn goto editpart; 6542118f387SNathan Whitehorn } 6552118f387SNathan Whitehorn gctl_free(r); 6562118f387SNathan Whitehorn 65750de5d07SNathan Whitehorn newfs_command(items[0].text, newfs, 1); 6582118f387SNathan Whitehorn set_default_part_metadata(pp->lg_name, scheme, items[0].text, 65950de5d07SNathan Whitehorn items[2].text, (strcmp(oldtype, items[0].text) != 0) ? 66050de5d07SNathan Whitehorn newfs : NULL); 6612118f387SNathan Whitehorn 662987415b1SNathan Whitehorn endedit: 663987415b1SNathan Whitehorn if (strcmp(oldtype, items[0].text) != 0 && cp != NULL) 664987415b1SNathan Whitehorn gpart_destroy(cp->lg_geom); 665987415b1SNathan Whitehorn if (strcmp(oldtype, items[0].text) != 0 && strcmp(items[0].text, 666987415b1SNathan Whitehorn "freebsd") == 0) 667987415b1SNathan Whitehorn gpart_partition(pp->lg_name, "BSD"); 668987415b1SNathan Whitehorn 66963128851SMarcelo Araujo for (i = 0; i < nitems(items); i++) 6702118f387SNathan Whitehorn if (items[i].text_free) 6712118f387SNathan Whitehorn free(items[i].text); 6722118f387SNathan Whitehorn } 6732118f387SNathan Whitehorn 6742118f387SNathan Whitehorn void 6752118f387SNathan Whitehorn set_default_part_metadata(const char *name, const char *scheme, 67650de5d07SNathan Whitehorn const char *type, const char *mountpoint, const char *newfs) 6772118f387SNathan Whitehorn { 6782118f387SNathan Whitehorn struct partition_metadata *md; 6796e15678aSNathan Whitehorn char *zpool_name = NULL; 68052f39da1SNathan Whitehorn const char *default_bootmount = NULL; 6816e15678aSNathan Whitehorn int i; 6822118f387SNathan Whitehorn 6832118f387SNathan Whitehorn /* Set part metadata */ 6842118f387SNathan Whitehorn md = get_part_metadata(name, 1); 6852118f387SNathan Whitehorn 6862118f387SNathan Whitehorn if (newfs) { 6872118f387SNathan Whitehorn if (md->newfs != NULL) { 6882118f387SNathan Whitehorn free(md->newfs); 6892118f387SNathan Whitehorn md->newfs = NULL; 6902118f387SNathan Whitehorn } 6912118f387SNathan Whitehorn 69250de5d07SNathan Whitehorn if (newfs != NULL && newfs[0] != '\0') { 69350de5d07SNathan Whitehorn md->newfs = malloc(strlen(newfs) + strlen(" /dev/") + 6946e15678aSNathan Whitehorn strlen(mountpoint) + 5 + strlen(name) + 1); 6956e15678aSNathan Whitehorn if (strcmp("freebsd-zfs", type) == 0) { 6966e15678aSNathan Whitehorn zpool_name = strdup((strlen(mountpoint) == 1) ? 6976e15678aSNathan Whitehorn "root" : &mountpoint[1]); 6986e15678aSNathan Whitehorn for (i = 0; zpool_name[i] != 0; i++) 6996e15678aSNathan Whitehorn if (!isalnum(zpool_name[i])) 7006e15678aSNathan Whitehorn zpool_name[i] = '_'; 7016e15678aSNathan Whitehorn sprintf(md->newfs, "%s %s /dev/%s", newfs, 7026e15678aSNathan Whitehorn zpool_name, name); 7036e15678aSNathan Whitehorn } else { 70450de5d07SNathan Whitehorn sprintf(md->newfs, "%s /dev/%s", newfs, name); 7052118f387SNathan Whitehorn } 7062118f387SNathan Whitehorn } 7076e15678aSNathan Whitehorn } 7082118f387SNathan Whitehorn 7092118f387SNathan Whitehorn if (strcmp(type, "freebsd-swap") == 0) 7102118f387SNathan Whitehorn mountpoint = "none"; 71152f39da1SNathan Whitehorn if (strcmp(type, bootpart_type(scheme, &default_bootmount)) == 0) { 712*db8b5613SRebecca Cran if (default_bootmount == NULL) { 713*db8b5613SRebecca Cran 714*db8b5613SRebecca Cran int fd = open("/tmp/bsdinstall-esps", O_CREAT | O_WRONLY | O_APPEND, 715*db8b5613SRebecca Cran 0600); 716*db8b5613SRebecca Cran if (fd > 0) { 717*db8b5613SRebecca Cran write(fd, md->name, strlen(md->name)); 718*db8b5613SRebecca Cran close(fd); 719*db8b5613SRebecca Cran } 720*db8b5613SRebecca Cran 7212118f387SNathan Whitehorn md->bootcode = 1; 722*db8b5613SRebecca Cran } 72352f39da1SNathan Whitehorn else if (mountpoint == NULL || strlen(mountpoint) == 0) 72452f39da1SNathan Whitehorn mountpoint = default_bootmount; 72552f39da1SNathan Whitehorn } 7262118f387SNathan Whitehorn 7276e15678aSNathan Whitehorn /* VTOC8 needs partcode at the start of partitions */ 7286e15678aSNathan Whitehorn if (strcmp(scheme, "VTOC8") == 0 && (strcmp(type, "freebsd-ufs") == 0 7296e15678aSNathan Whitehorn || strcmp(type, "freebsd-zfs") == 0)) 7302118f387SNathan Whitehorn md->bootcode = 1; 7312118f387SNathan Whitehorn 7322118f387SNathan Whitehorn if (mountpoint == NULL || mountpoint[0] == '\0') { 7332118f387SNathan Whitehorn if (md->fstab != NULL) { 7342118f387SNathan Whitehorn free(md->fstab->fs_spec); 7352118f387SNathan Whitehorn free(md->fstab->fs_file); 7362118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 7372118f387SNathan Whitehorn free(md->fstab->fs_mntops); 7382118f387SNathan Whitehorn free(md->fstab->fs_type); 7392118f387SNathan Whitehorn free(md->fstab); 7402118f387SNathan Whitehorn md->fstab = NULL; 7412118f387SNathan Whitehorn } 7422118f387SNathan Whitehorn } else { 7432118f387SNathan Whitehorn if (md->fstab == NULL) { 7442118f387SNathan Whitehorn md->fstab = malloc(sizeof(struct fstab)); 7452118f387SNathan Whitehorn } else { 7462118f387SNathan Whitehorn free(md->fstab->fs_spec); 7472118f387SNathan Whitehorn free(md->fstab->fs_file); 7482118f387SNathan Whitehorn free(md->fstab->fs_vfstype); 7492118f387SNathan Whitehorn free(md->fstab->fs_mntops); 7502118f387SNathan Whitehorn free(md->fstab->fs_type); 7512118f387SNathan Whitehorn } 7526e15678aSNathan Whitehorn if (strcmp("freebsd-zfs", type) == 0) { 7536e15678aSNathan Whitehorn md->fstab->fs_spec = strdup(zpool_name); 7546e15678aSNathan Whitehorn } else { 7556e15678aSNathan Whitehorn md->fstab->fs_spec = malloc(strlen(name) + 7566e15678aSNathan Whitehorn strlen("/dev/") + 1); 7572118f387SNathan Whitehorn sprintf(md->fstab->fs_spec, "/dev/%s", name); 7586e15678aSNathan Whitehorn } 7592118f387SNathan Whitehorn md->fstab->fs_file = strdup(mountpoint); 7602118f387SNathan Whitehorn /* Get VFS from text after freebsd-, if possible */ 76150de5d07SNathan Whitehorn if (strncmp("freebsd-", type, 8) == 0) 7622118f387SNathan Whitehorn md->fstab->fs_vfstype = strdup(&type[8]); 7639f7602f0SNathan Whitehorn else if (strcmp("fat32", type) == 0 || strcmp("efi", type) == 0 7649f7602f0SNathan Whitehorn || strcmp("ms-basic-data", type) == 0) 76550de5d07SNathan Whitehorn md->fstab->fs_vfstype = strdup("msdosfs"); 7662118f387SNathan Whitehorn else 7672118f387SNathan Whitehorn md->fstab->fs_vfstype = strdup(type); /* Guess */ 7682118f387SNathan Whitehorn if (strcmp(type, "freebsd-swap") == 0) { 7692118f387SNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_SW); 7702118f387SNathan Whitehorn md->fstab->fs_freq = 0; 7712118f387SNathan Whitehorn md->fstab->fs_passno = 0; 7726e15678aSNathan Whitehorn } else if (strcmp(type, "freebsd-zfs") == 0) { 7736e15678aSNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_RW); 7746e15678aSNathan Whitehorn md->fstab->fs_freq = 0; 7756e15678aSNathan Whitehorn md->fstab->fs_passno = 0; 7762118f387SNathan Whitehorn } else { 7772118f387SNathan Whitehorn md->fstab->fs_type = strdup(FSTAB_RW); 7782118f387SNathan Whitehorn if (strcmp(mountpoint, "/") == 0) { 7792118f387SNathan Whitehorn md->fstab->fs_freq = 1; 7802118f387SNathan Whitehorn md->fstab->fs_passno = 1; 7812118f387SNathan Whitehorn } else { 7822118f387SNathan Whitehorn md->fstab->fs_freq = 2; 7832118f387SNathan Whitehorn md->fstab->fs_passno = 2; 7842118f387SNathan Whitehorn } 7852118f387SNathan Whitehorn } 7862118f387SNathan Whitehorn md->fstab->fs_mntops = strdup(md->fstab->fs_type); 7872118f387SNathan Whitehorn } 7886e15678aSNathan Whitehorn 7896e15678aSNathan Whitehorn if (zpool_name != NULL) 7906e15678aSNathan Whitehorn free(zpool_name); 7912118f387SNathan Whitehorn } 7922118f387SNathan Whitehorn 7932118f387SNathan Whitehorn static 7942118f387SNathan Whitehorn int part_compare(const void *xa, const void *xb) 7952118f387SNathan Whitehorn { 7962118f387SNathan Whitehorn struct gprovider **a = (struct gprovider **)xa; 7972118f387SNathan Whitehorn struct gprovider **b = (struct gprovider **)xb; 7982118f387SNathan Whitehorn intmax_t astart, bstart; 7992118f387SNathan Whitehorn struct gconfig *gc; 8002118f387SNathan Whitehorn 8012118f387SNathan Whitehorn astart = bstart = 0; 8022118f387SNathan Whitehorn LIST_FOREACH(gc, &(*a)->lg_config, lg_config) 8032118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) { 8042118f387SNathan Whitehorn astart = strtoimax(gc->lg_val, NULL, 0); 8052118f387SNathan Whitehorn break; 8062118f387SNathan Whitehorn } 8072118f387SNathan Whitehorn LIST_FOREACH(gc, &(*b)->lg_config, lg_config) 8082118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) { 8092118f387SNathan Whitehorn bstart = strtoimax(gc->lg_val, NULL, 0); 8102118f387SNathan Whitehorn break; 8112118f387SNathan Whitehorn } 8122118f387SNathan Whitehorn 8132118f387SNathan Whitehorn if (astart < bstart) 8142118f387SNathan Whitehorn return -1; 8152118f387SNathan Whitehorn else if (astart > bstart) 8162118f387SNathan Whitehorn return 1; 8172118f387SNathan Whitehorn else 8182118f387SNathan Whitehorn return 0; 8192118f387SNathan Whitehorn } 8202118f387SNathan Whitehorn 8212118f387SNathan Whitehorn intmax_t 8222118f387SNathan Whitehorn gpart_max_free(struct ggeom *geom, intmax_t *npartstart) 8232118f387SNathan Whitehorn { 8242118f387SNathan Whitehorn struct gconfig *gc; 8252118f387SNathan Whitehorn struct gprovider *pp, **providers; 82647ead00dSDag-Erling Smørgrav intmax_t sectorsize, stripesize, offset; 8272118f387SNathan Whitehorn intmax_t lastend; 8282118f387SNathan Whitehorn intmax_t start, end; 8292118f387SNathan Whitehorn intmax_t maxsize, maxstart; 8302118f387SNathan Whitehorn intmax_t partstart, partend; 8312118f387SNathan Whitehorn int i, nparts; 8322118f387SNathan Whitehorn 8332118f387SNathan Whitehorn /* Now get the maximum free size and free start */ 8342118f387SNathan Whitehorn start = end = 0; 8352118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) { 8362118f387SNathan Whitehorn if (strcmp(gc->lg_name, "first") == 0) 8372118f387SNathan Whitehorn start = strtoimax(gc->lg_val, NULL, 0); 8382118f387SNathan Whitehorn if (strcmp(gc->lg_name, "last") == 0) 8392118f387SNathan Whitehorn end = strtoimax(gc->lg_val, NULL, 0); 8402118f387SNathan Whitehorn } 8412118f387SNathan Whitehorn 8422118f387SNathan Whitehorn i = nparts = 0; 8432118f387SNathan Whitehorn LIST_FOREACH(pp, &geom->lg_provider, lg_provider) 8442118f387SNathan Whitehorn nparts++; 8452118f387SNathan Whitehorn providers = calloc(nparts, sizeof(providers[0])); 8462118f387SNathan Whitehorn LIST_FOREACH(pp, &geom->lg_provider, lg_provider) 8472118f387SNathan Whitehorn providers[i++] = pp; 8482118f387SNathan Whitehorn qsort(providers, nparts, sizeof(providers[0]), part_compare); 8492118f387SNathan Whitehorn 8502118f387SNathan Whitehorn lastend = start - 1; 8512118f387SNathan Whitehorn maxsize = 0; 8522118f387SNathan Whitehorn for (i = 0; i < nparts; i++) { 8532118f387SNathan Whitehorn pp = providers[i]; 8542118f387SNathan Whitehorn 8552118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 8562118f387SNathan Whitehorn if (strcmp(gc->lg_name, "start") == 0) 8572118f387SNathan Whitehorn partstart = strtoimax(gc->lg_val, NULL, 0); 8582118f387SNathan Whitehorn if (strcmp(gc->lg_name, "end") == 0) 8592118f387SNathan Whitehorn partend = strtoimax(gc->lg_val, NULL, 0); 8602118f387SNathan Whitehorn } 8612118f387SNathan Whitehorn 8622118f387SNathan Whitehorn if (partstart - lastend > maxsize) { 8632118f387SNathan Whitehorn maxsize = partstart - lastend - 1; 8642118f387SNathan Whitehorn maxstart = lastend + 1; 8652118f387SNathan Whitehorn } 8662118f387SNathan Whitehorn 8672118f387SNathan Whitehorn lastend = partend; 8682118f387SNathan Whitehorn } 8692118f387SNathan Whitehorn 8702118f387SNathan Whitehorn if (end - lastend > maxsize) { 8718c7de243SNathan Whitehorn maxsize = end - lastend; 8722118f387SNathan Whitehorn maxstart = lastend + 1; 8732118f387SNathan Whitehorn } 8742118f387SNathan Whitehorn 8752118f387SNathan Whitehorn pp = LIST_FIRST(&geom->lg_consumer)->lg_provider; 8762118f387SNathan Whitehorn 87747ead00dSDag-Erling Smørgrav /* 87847ead00dSDag-Erling Smørgrav * Round the start and size of the largest available space up to 87947ead00dSDag-Erling Smørgrav * the nearest multiple of the adjusted stripe size. 88047ead00dSDag-Erling Smørgrav * 88147ead00dSDag-Erling Smørgrav * The adjusted stripe size is the least common multiple of the 88247ead00dSDag-Erling Smørgrav * actual stripe size, or the sector size if no stripe size was 88347ead00dSDag-Erling Smørgrav * reported, and 4096. The reason for this is that contemporary 88447ead00dSDag-Erling Smørgrav * disks often have 4096-byte physical sectors but report 512 88547ead00dSDag-Erling Smørgrav * bytes instead for compatibility with older / broken operating 88647ead00dSDag-Erling Smørgrav * systems and BIOSes. For the same reasons, virtualized storage 88747ead00dSDag-Erling Smørgrav * may also report a 512-byte stripe size, or none at all. 88847ead00dSDag-Erling Smørgrav */ 88947ead00dSDag-Erling Smørgrav sectorsize = pp->lg_sectorsize; 89047ead00dSDag-Erling Smørgrav if ((stripesize = pp->lg_stripesize) == 0) 89147ead00dSDag-Erling Smørgrav stripesize = sectorsize; 89247ead00dSDag-Erling Smørgrav while (stripesize % 4096 != 0) 89347ead00dSDag-Erling Smørgrav stripesize *= 2; 89447ead00dSDag-Erling Smørgrav if ((offset = maxstart * sectorsize % stripesize) != 0) { 89547ead00dSDag-Erling Smørgrav offset = (stripesize - offset) / sectorsize; 8962118f387SNathan Whitehorn maxstart += offset; 8972118f387SNathan Whitehorn maxsize -= offset; 8982118f387SNathan Whitehorn } 8992118f387SNathan Whitehorn 9002118f387SNathan Whitehorn if (npartstart != NULL) 9012118f387SNathan Whitehorn *npartstart = maxstart; 9022118f387SNathan Whitehorn 9032118f387SNathan Whitehorn return (maxsize); 9042118f387SNathan Whitehorn } 9052118f387SNathan Whitehorn 90652f39da1SNathan Whitehorn static size_t 90752f39da1SNathan Whitehorn add_boot_partition(struct ggeom *geom, struct gprovider *pp, 90852f39da1SNathan Whitehorn const char *scheme, int interactive) 90952f39da1SNathan Whitehorn { 91052f39da1SNathan Whitehorn struct gconfig *gc; 91152f39da1SNathan Whitehorn struct gprovider *ppi; 91252f39da1SNathan Whitehorn int choice; 91352f39da1SNathan Whitehorn 91452f39da1SNathan Whitehorn /* Check for existing freebsd-boot partition */ 91552f39da1SNathan Whitehorn LIST_FOREACH(ppi, &geom->lg_provider, lg_provider) { 91652f39da1SNathan Whitehorn struct partition_metadata *md; 91752f39da1SNathan Whitehorn const char *bootmount = NULL; 91852f39da1SNathan Whitehorn 91952f39da1SNathan Whitehorn LIST_FOREACH(gc, &ppi->lg_config, lg_config) 92052f39da1SNathan Whitehorn if (strcmp(gc->lg_name, "type") == 0) 92152f39da1SNathan Whitehorn break; 92252f39da1SNathan Whitehorn if (gc == NULL) 92352f39da1SNathan Whitehorn continue; 92452f39da1SNathan Whitehorn if (strcmp(gc->lg_val, bootpart_type(scheme, &bootmount)) != 0) 92552f39da1SNathan Whitehorn continue; 92652f39da1SNathan Whitehorn 92752f39da1SNathan Whitehorn /* 92852f39da1SNathan Whitehorn * If the boot partition is not mountable and needs partcode, 92952f39da1SNathan Whitehorn * but doesn't have it, it doesn't satisfy our requirements. 93052f39da1SNathan Whitehorn */ 93152f39da1SNathan Whitehorn md = get_part_metadata(ppi->lg_name, 0); 93252f39da1SNathan Whitehorn if (bootmount == NULL && (md == NULL || !md->bootcode)) 93352f39da1SNathan Whitehorn continue; 93452f39da1SNathan Whitehorn 93552f39da1SNathan Whitehorn /* If it is mountable, but mounted somewhere else, remount */ 93652f39da1SNathan Whitehorn if (bootmount != NULL && md != NULL && md->fstab != NULL 93752f39da1SNathan Whitehorn && strlen(md->fstab->fs_file) > 0 93852f39da1SNathan Whitehorn && strcmp(md->fstab->fs_file, bootmount) != 0) 93952f39da1SNathan Whitehorn continue; 94052f39da1SNathan Whitehorn 94152f39da1SNathan Whitehorn /* If it is mountable, but mountpoint is not set, mount it */ 94252f39da1SNathan Whitehorn if (bootmount != NULL && md == NULL) 94352f39da1SNathan Whitehorn set_default_part_metadata(ppi->lg_name, scheme, 94452f39da1SNathan Whitehorn gc->lg_val, bootmount, NULL); 94552f39da1SNathan Whitehorn 94652f39da1SNathan Whitehorn /* Looks good at this point, no added data needed */ 94752f39da1SNathan Whitehorn return (0); 94852f39da1SNathan Whitehorn } 94952f39da1SNathan Whitehorn 95052f39da1SNathan Whitehorn if (interactive) 95152f39da1SNathan Whitehorn choice = dialog_yesno("Boot Partition", 95252f39da1SNathan Whitehorn "This partition scheme requires a boot partition " 95352f39da1SNathan Whitehorn "for the disk to be bootable. Would you like to " 95452f39da1SNathan Whitehorn "make one now?", 0, 0); 95552f39da1SNathan Whitehorn else 95652f39da1SNathan Whitehorn choice = 0; 95752f39da1SNathan Whitehorn 95852f39da1SNathan Whitehorn if (choice == 0) { /* yes */ 9596134b186SNathan Whitehorn struct partition_metadata *md; 96052f39da1SNathan Whitehorn const char *bootmount = NULL; 9616134b186SNathan Whitehorn char *bootpartname = NULL; 96252f39da1SNathan Whitehorn char sizestr[7]; 96352f39da1SNathan Whitehorn 96452f39da1SNathan Whitehorn humanize_number(sizestr, 7, 96552f39da1SNathan Whitehorn bootpart_size(scheme), "B", HN_AUTOSCALE, 96652f39da1SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 96752f39da1SNathan Whitehorn 96852f39da1SNathan Whitehorn gpart_create(pp, bootpart_type(scheme, &bootmount), 9696134b186SNathan Whitehorn sizestr, bootmount, &bootpartname, 0); 9706134b186SNathan Whitehorn 9716134b186SNathan Whitehorn if (bootpartname == NULL) /* Error reported to user already */ 9726134b186SNathan Whitehorn return 0; 9736134b186SNathan Whitehorn 9746134b186SNathan Whitehorn /* If the part is not mountable, make sure newfs isn't set */ 9756134b186SNathan Whitehorn if (bootmount == NULL) { 9766134b186SNathan Whitehorn md = get_part_metadata(bootpartname, 0); 9776134b186SNathan Whitehorn if (md != NULL && md->newfs != NULL) { 9786134b186SNathan Whitehorn free(md->newfs); 9796134b186SNathan Whitehorn md->newfs = NULL; 9806134b186SNathan Whitehorn } 9816134b186SNathan Whitehorn } 9826134b186SNathan Whitehorn 9836134b186SNathan Whitehorn free(bootpartname); 98452f39da1SNathan Whitehorn 98552f39da1SNathan Whitehorn return (bootpart_size(scheme)); 98652f39da1SNathan Whitehorn } 98752f39da1SNathan Whitehorn 98852f39da1SNathan Whitehorn return (0); 98952f39da1SNathan Whitehorn } 99052f39da1SNathan Whitehorn 9912118f387SNathan Whitehorn void 99252f39da1SNathan Whitehorn gpart_create(struct gprovider *pp, const char *default_type, 99352f39da1SNathan Whitehorn const char *default_size, const char *default_mountpoint, 99452f39da1SNathan Whitehorn char **partname, int interactive) 9952118f387SNathan Whitehorn { 9962118f387SNathan Whitehorn struct gctl_req *r; 9972118f387SNathan Whitehorn struct gconfig *gc; 9982118f387SNathan Whitehorn struct gconsumer *cp; 9992118f387SNathan Whitehorn struct ggeom *geom; 10002118f387SNathan Whitehorn const char *errstr, *scheme; 10017899c6c1SNathan Whitehorn char sizestr[32], startstr[32], output[64], *newpartname; 10026e15678aSNathan Whitehorn char newfs[255], options_fstype[64]; 10032118f387SNathan Whitehorn intmax_t maxsize, size, sector, firstfree, stripe; 10042118f387SNathan Whitehorn uint64_t bytes; 10052118f387SNathan Whitehorn int nitems, choice, junk; 10062118f387SNathan Whitehorn unsigned i; 10072118f387SNathan Whitehorn 10082118f387SNathan Whitehorn DIALOG_FORMITEM items[] = { 10092118f387SNathan Whitehorn {0, "Type:", 5, 0, 0, FALSE, "freebsd-ufs", 11, 0, 12, 15, 0, 10106e15678aSNathan Whitehorn FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, " 10116e15678aSNathan Whitehorn "freebsd-swap)", FALSE}, 10122118f387SNathan Whitehorn {0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 15, 0, 10132118f387SNathan Whitehorn FALSE, "Partition size. Append K, M, G for kilobytes, " 10142118f387SNathan Whitehorn "megabytes or gigabytes.", FALSE}, 10152118f387SNathan Whitehorn {0, "Mountpoint:", 11, 2, 0, FALSE, "", 11, 2, 12, 15, 0, 10162118f387SNathan Whitehorn FALSE, "Path at which to mount partition (blank for " 10172118f387SNathan Whitehorn "swap, / for root filesystem)", FALSE}, 10182118f387SNathan Whitehorn {0, "Label:", 7, 3, 0, FALSE, "", 11, 3, 12, 15, 0, FALSE, 10192118f387SNathan Whitehorn "Partition name. Not all partition schemes support this.", 10202118f387SNathan Whitehorn FALSE}, 10212118f387SNathan Whitehorn }; 10222118f387SNathan Whitehorn 10232118f387SNathan Whitehorn if (partname != NULL) 10242118f387SNathan Whitehorn *partname = NULL; 10252118f387SNathan Whitehorn 10262118f387SNathan Whitehorn /* Record sector and stripe sizes */ 10272118f387SNathan Whitehorn sector = pp->lg_sectorsize; 10282118f387SNathan Whitehorn stripe = pp->lg_stripesize; 10292118f387SNathan Whitehorn 10302118f387SNathan Whitehorn /* 10312118f387SNathan Whitehorn * Find the PART geom we are manipulating. This may be a consumer of 10322118f387SNathan Whitehorn * this provider, or its parent. Check the consumer case first. 10332118f387SNathan Whitehorn */ 10342118f387SNathan Whitehorn geom = NULL; 10352118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 10362118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 10372118f387SNathan Whitehorn geom = cp->lg_geom; 10382118f387SNathan Whitehorn break; 10392118f387SNathan Whitehorn } 10402118f387SNathan Whitehorn 10412118f387SNathan Whitehorn if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0) 10422118f387SNathan Whitehorn geom = pp->lg_geom; 10432118f387SNathan Whitehorn 10442118f387SNathan Whitehorn /* Now get the partition scheme */ 10452118f387SNathan Whitehorn scheme = NULL; 10462118f387SNathan Whitehorn if (geom != NULL) { 10472118f387SNathan Whitehorn LIST_FOREACH(gc, &geom->lg_config, lg_config) 10482118f387SNathan Whitehorn if (strcmp(gc->lg_name, "scheme") == 0) 10492118f387SNathan Whitehorn scheme = gc->lg_val; 10502118f387SNathan Whitehorn } 10512118f387SNathan Whitehorn 10522118f387SNathan Whitehorn if (geom == NULL || scheme == NULL || strcmp(scheme, "(none)") == 0) { 1053bcc25b7eSNathan Whitehorn if (gpart_partition(pp->lg_name, NULL) == 0) 10542118f387SNathan Whitehorn dialog_msgbox("", 10552118f387SNathan Whitehorn "The partition table has been successfully created." 10562118f387SNathan Whitehorn " Please press Create again to create partitions.", 10572118f387SNathan Whitehorn 0, 0, TRUE); 10582118f387SNathan Whitehorn 10592118f387SNathan Whitehorn return; 10602118f387SNathan Whitehorn } 10612118f387SNathan Whitehorn 10622118f387SNathan Whitehorn /* 10632118f387SNathan Whitehorn * If we still don't have a geom, either the user has 10642118f387SNathan Whitehorn * canceled partitioning or there has been an error which has already 10652118f387SNathan Whitehorn * been displayed, so bail. 10662118f387SNathan Whitehorn */ 10672118f387SNathan Whitehorn if (geom == NULL) 10682118f387SNathan Whitehorn return; 10692118f387SNathan Whitehorn 10702118f387SNathan Whitehorn maxsize = size = gpart_max_free(geom, &firstfree); 10712118f387SNathan Whitehorn if (size <= 0) { 10722118f387SNathan Whitehorn dialog_msgbox("Error", "No free space left on device.", 0, 0, 10732118f387SNathan Whitehorn TRUE); 10742118f387SNathan Whitehorn return; 10752118f387SNathan Whitehorn } 10762118f387SNathan Whitehorn 10772118f387SNathan Whitehorn humanize_number(sizestr, 7, size*sector, "B", HN_AUTOSCALE, 10782118f387SNathan Whitehorn HN_NOSPACE | HN_DECIMAL); 10792118f387SNathan Whitehorn items[1].text = sizestr; 10802118f387SNathan Whitehorn 10812118f387SNathan Whitehorn /* Special-case the MBR default type for nested partitions */ 10822b375b4eSYoshihiro Takahashi if (strcmp(scheme, "MBR") == 0) { 10832118f387SNathan Whitehorn items[0].text = "freebsd"; 1084bcc25b7eSNathan Whitehorn items[0].help = "Filesystem type (e.g. freebsd, fat32)"; 1085bcc25b7eSNathan Whitehorn } 10862118f387SNathan Whitehorn 1087c67f41d0SNathan Whitehorn nitems = scheme_supports_labels(scheme) ? 4 : 3; 10882118f387SNathan Whitehorn 10892118f387SNathan Whitehorn if (default_type != NULL) 109052f39da1SNathan Whitehorn items[0].text = (char *)default_type; 10912118f387SNathan Whitehorn if (default_size != NULL) 109252f39da1SNathan Whitehorn items[1].text = (char *)default_size; 10932118f387SNathan Whitehorn if (default_mountpoint != NULL) 109452f39da1SNathan Whitehorn items[2].text = (char *)default_mountpoint; 10952118f387SNathan Whitehorn 109650de5d07SNathan Whitehorn /* Default options */ 109750de5d07SNathan Whitehorn strncpy(options_fstype, items[0].text, 109850de5d07SNathan Whitehorn sizeof(options_fstype)); 109950de5d07SNathan Whitehorn newfs_command(options_fstype, newfs, 1); 11002118f387SNathan Whitehorn addpartform: 11012118f387SNathan Whitehorn if (interactive) { 110250de5d07SNathan Whitehorn dialog_vars.extra_label = "Options"; 110350de5d07SNathan Whitehorn dialog_vars.extra_button = TRUE; 11042118f387SNathan Whitehorn choice = dlg_form("Add Partition", "", 0, 0, 0, nitems, 11052118f387SNathan Whitehorn items, &junk); 110650de5d07SNathan Whitehorn dialog_vars.extra_button = FALSE; 110750de5d07SNathan Whitehorn switch (choice) { 110850de5d07SNathan Whitehorn case 0: /* OK */ 110950de5d07SNathan Whitehorn break; 111050de5d07SNathan Whitehorn case 1: /* Cancel */ 11112118f387SNathan Whitehorn return; 111250de5d07SNathan Whitehorn case 3: /* Options */ 111350de5d07SNathan Whitehorn strncpy(options_fstype, items[0].text, 111450de5d07SNathan Whitehorn sizeof(options_fstype)); 111550de5d07SNathan Whitehorn newfs_command(options_fstype, newfs, 0); 111650de5d07SNathan Whitehorn goto addpartform; 111750de5d07SNathan Whitehorn } 111850de5d07SNathan Whitehorn } 111950de5d07SNathan Whitehorn 112050de5d07SNathan Whitehorn /* 112150de5d07SNathan Whitehorn * If the user changed the fs type after specifying options, undo 112250de5d07SNathan Whitehorn * their choices in favor of the new filesystem's defaults. 112350de5d07SNathan Whitehorn */ 11240d49c6d5SNathan Whitehorn if (strcmp(options_fstype, items[0].text) != 0) { 112550de5d07SNathan Whitehorn strncpy(options_fstype, items[0].text, sizeof(options_fstype)); 112650de5d07SNathan Whitehorn newfs_command(options_fstype, newfs, 1); 11272118f387SNathan Whitehorn } 11282118f387SNathan Whitehorn 11292118f387SNathan Whitehorn size = maxsize; 11302118f387SNathan Whitehorn if (strlen(items[1].text) > 0) { 11312118f387SNathan Whitehorn if (expand_number(items[1].text, &bytes) != 0) { 11322118f387SNathan Whitehorn char error[512]; 11332118f387SNathan Whitehorn 11342118f387SNathan Whitehorn sprintf(error, "Invalid size: %s\n", strerror(errno)); 11352118f387SNathan Whitehorn dialog_msgbox("Error", error, 0, 0, TRUE); 11362118f387SNathan Whitehorn goto addpartform; 11372118f387SNathan Whitehorn } 11382118f387SNathan Whitehorn size = MIN((intmax_t)(bytes/sector), maxsize); 11392118f387SNathan Whitehorn } 11402118f387SNathan Whitehorn 11412118f387SNathan Whitehorn /* Check if the label has a / in it */ 11422118f387SNathan Whitehorn if (strchr(items[3].text, '/') != NULL) { 11432118f387SNathan Whitehorn dialog_msgbox("Error", "Label contains a /, which is not an " 11442118f387SNathan Whitehorn "allowed character.", 0, 0, TRUE); 11452118f387SNathan Whitehorn goto addpartform; 11462118f387SNathan Whitehorn } 11472118f387SNathan Whitehorn 11482118f387SNathan Whitehorn /* Warn if no mountpoint set */ 11492118f387SNathan Whitehorn if (strcmp(items[0].text, "freebsd-ufs") == 0 && 11502118f387SNathan Whitehorn items[2].text[0] != '/') { 115140f0d8dcSRavi Pokala choice = 0; 115240f0d8dcSRavi Pokala if (interactive) { 11532118f387SNathan Whitehorn dialog_vars.defaultno = TRUE; 11542118f387SNathan Whitehorn choice = dialog_yesno("Warning", 11552118f387SNathan Whitehorn "This partition does not have a valid mountpoint " 11562118f387SNathan Whitehorn "(for the partition from which you intend to boot the " 11572118f387SNathan Whitehorn "operating system, the mountpoint should be /). Are you " 11582118f387SNathan Whitehorn "sure you want to continue?" 11592118f387SNathan Whitehorn , 0, 0); 11602118f387SNathan Whitehorn dialog_vars.defaultno = FALSE; 116140f0d8dcSRavi Pokala } 11622118f387SNathan Whitehorn if (choice == 1) /* cancel */ 11632118f387SNathan Whitehorn goto addpartform; 11642118f387SNathan Whitehorn } 11652118f387SNathan Whitehorn 1166a780c996SNathan Whitehorn /* 1167a780c996SNathan Whitehorn * Error if this scheme needs nested partitions, this is one, and 1168a780c996SNathan Whitehorn * a mountpoint was set. 1169a780c996SNathan Whitehorn */ 1170a780c996SNathan Whitehorn if (strcmp(items[0].text, "freebsd") == 0 && 1171a780c996SNathan Whitehorn strlen(items[2].text) > 0) { 1172a780c996SNathan Whitehorn dialog_msgbox("Error", "Partitions of type \"freebsd\" are " 1173a780c996SNathan Whitehorn "nested BSD-type partition schemes and cannot have " 1174a780c996SNathan Whitehorn "mountpoints. After creating one, select it and press " 1175a780c996SNathan Whitehorn "Create again to add the actual file systems.", 0, 0, TRUE); 1176a780c996SNathan Whitehorn goto addpartform; 1177a780c996SNathan Whitehorn } 1178a780c996SNathan Whitehorn 11792118f387SNathan Whitehorn /* If this is the root partition, check that this scheme is bootable */ 11802118f387SNathan Whitehorn if (strcmp(items[2].text, "/") == 0 && !is_scheme_bootable(scheme)) { 11812118f387SNathan Whitehorn char message[512]; 11822118f387SNathan Whitehorn sprintf(message, "This partition scheme (%s) is not bootable " 11832118f387SNathan Whitehorn "on this platform. Are you sure you want to proceed?", 11842118f387SNathan Whitehorn scheme); 11852118f387SNathan Whitehorn dialog_vars.defaultno = TRUE; 11862118f387SNathan Whitehorn choice = dialog_yesno("Warning", message, 0, 0); 11872118f387SNathan Whitehorn dialog_vars.defaultno = FALSE; 11882118f387SNathan Whitehorn if (choice == 1) /* cancel */ 11892118f387SNathan Whitehorn goto addpartform; 11902118f387SNathan Whitehorn } 11912118f387SNathan Whitehorn 11926e15678aSNathan Whitehorn /* If this is the root partition, check that this fs is bootable */ 11936e15678aSNathan Whitehorn if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme, 11946e15678aSNathan Whitehorn items[0].text)) { 11956e15678aSNathan Whitehorn char message[512]; 11966e15678aSNathan Whitehorn sprintf(message, "This file system (%s) is not bootable " 11976e15678aSNathan Whitehorn "on this system. Are you sure you want to proceed?", 11986e15678aSNathan Whitehorn items[0].text); 11996e15678aSNathan Whitehorn dialog_vars.defaultno = TRUE; 12006e15678aSNathan Whitehorn choice = dialog_yesno("Warning", message, 0, 0); 12016e15678aSNathan Whitehorn dialog_vars.defaultno = FALSE; 12026e15678aSNathan Whitehorn if (choice == 1) /* cancel */ 12036e15678aSNathan Whitehorn goto addpartform; 12046e15678aSNathan Whitehorn } 12056e15678aSNathan Whitehorn 12062118f387SNathan Whitehorn /* 12072118f387SNathan Whitehorn * If this is the root partition, and we need a boot partition, ask 12082118f387SNathan Whitehorn * the user to add one. 12092118f387SNathan Whitehorn */ 1210a780c996SNathan Whitehorn 12118d795806SNathan Whitehorn if ((strcmp(items[0].text, "freebsd") == 0 || 121252f39da1SNathan Whitehorn strcmp(items[2].text, "/") == 0) && bootpart_size(scheme) > 0) { 121352f39da1SNathan Whitehorn size_t bytes = add_boot_partition(geom, pp, scheme, 121452f39da1SNathan Whitehorn interactive); 12152118f387SNathan Whitehorn 12162118f387SNathan Whitehorn /* Now adjust the part we are really adding forward */ 121752f39da1SNathan Whitehorn if (bytes > 0) { 121852f39da1SNathan Whitehorn firstfree += bytes / sector; 121952f39da1SNathan Whitehorn size -= (bytes + stripe)/sector; 12202118f387SNathan Whitehorn if (stripe > 0 && (firstfree*sector % stripe) != 0) 12212118f387SNathan Whitehorn firstfree += (stripe - ((firstfree*sector) % 12222118f387SNathan Whitehorn stripe)) / sector; 12232118f387SNathan Whitehorn } 12242118f387SNathan Whitehorn } 12252118f387SNathan Whitehorn 12262118f387SNathan Whitehorn r = gctl_get_handle(); 12272118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 12282118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 12292118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 12302118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "add"); 12312118f387SNathan Whitehorn 12322118f387SNathan Whitehorn gctl_ro_param(r, "type", -1, items[0].text); 12332118f387SNathan Whitehorn snprintf(sizestr, sizeof(sizestr), "%jd", size); 12342118f387SNathan Whitehorn gctl_ro_param(r, "size", -1, sizestr); 12352118f387SNathan Whitehorn snprintf(startstr, sizeof(startstr), "%jd", firstfree); 12362118f387SNathan Whitehorn gctl_ro_param(r, "start", -1, startstr); 12372118f387SNathan Whitehorn if (items[3].text[0] != '\0') 12382118f387SNathan Whitehorn gctl_ro_param(r, "label", -1, items[3].text); 12392118f387SNathan Whitehorn gctl_rw_param(r, "output", sizeof(output), output); 12402118f387SNathan Whitehorn errstr = gctl_issue(r); 12412118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 12422118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 12432118f387SNathan Whitehorn gctl_free(r); 12442118f387SNathan Whitehorn goto addpartform; 12452118f387SNathan Whitehorn } 12467899c6c1SNathan Whitehorn newpartname = strtok(output, " "); 12477899c6c1SNathan Whitehorn gctl_free(r); 12487899c6c1SNathan Whitehorn 12497899c6c1SNathan Whitehorn /* 12507899c6c1SNathan Whitehorn * Try to destroy any geom that gpart picked up already here from 12517899c6c1SNathan Whitehorn * dirty blocks. 12527899c6c1SNathan Whitehorn */ 12537899c6c1SNathan Whitehorn r = gctl_get_handle(); 12547899c6c1SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 12557899c6c1SNathan Whitehorn gctl_ro_param(r, "arg0", -1, newpartname); 12567899c6c1SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 12577899c6c1SNathan Whitehorn junk = 1; 12587899c6c1SNathan Whitehorn gctl_ro_param(r, "force", sizeof(junk), &junk); 12597899c6c1SNathan Whitehorn gctl_ro_param(r, "verb", -1, "destroy"); 12607899c6c1SNathan Whitehorn gctl_issue(r); /* Error usually expected and non-fatal */ 12617899c6c1SNathan Whitehorn gctl_free(r); 12622118f387SNathan Whitehorn 126352f39da1SNathan Whitehorn 126452f39da1SNathan Whitehorn if (strcmp(items[0].text, "freebsd") == 0) 12657899c6c1SNathan Whitehorn gpart_partition(newpartname, "BSD"); 12662118f387SNathan Whitehorn else 12677899c6c1SNathan Whitehorn set_default_part_metadata(newpartname, scheme, 126850de5d07SNathan Whitehorn items[0].text, items[2].text, newfs); 12692118f387SNathan Whitehorn 127063128851SMarcelo Araujo for (i = 0; i < nitems(items); i++) 12712118f387SNathan Whitehorn if (items[i].text_free) 12722118f387SNathan Whitehorn free(items[i].text); 12732118f387SNathan Whitehorn 12742118f387SNathan Whitehorn if (partname != NULL) 12757899c6c1SNathan Whitehorn *partname = strdup(newpartname); 12762118f387SNathan Whitehorn } 12772118f387SNathan Whitehorn 12782118f387SNathan Whitehorn void 12792118f387SNathan Whitehorn gpart_delete(struct gprovider *pp) 12802118f387SNathan Whitehorn { 12812118f387SNathan Whitehorn struct gconfig *gc; 12822118f387SNathan Whitehorn struct ggeom *geom; 12832118f387SNathan Whitehorn struct gconsumer *cp; 12842118f387SNathan Whitehorn struct gctl_req *r; 12852118f387SNathan Whitehorn const char *errstr; 12862118f387SNathan Whitehorn intmax_t idx; 1287f36a5e0fSNathan Whitehorn int is_partition; 12882118f387SNathan Whitehorn 12892118f387SNathan Whitehorn /* Is it a partition? */ 12902118f387SNathan Whitehorn is_partition = (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0); 12912118f387SNathan Whitehorn 12922118f387SNathan Whitehorn /* Find out if this is the root of a gpart geom */ 12932118f387SNathan Whitehorn geom = NULL; 12942118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 12952118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) { 12962118f387SNathan Whitehorn geom = cp->lg_geom; 12972118f387SNathan Whitehorn break; 12982118f387SNathan Whitehorn } 12992118f387SNathan Whitehorn 1300f36a5e0fSNathan Whitehorn /* If so, destroy all children */ 13012118f387SNathan Whitehorn if (geom != NULL) { 1302f36a5e0fSNathan Whitehorn gpart_destroy(geom); 1303f36a5e0fSNathan Whitehorn 1304f36a5e0fSNathan Whitehorn /* If this is a partition, revert it, so it can be deleted */ 13052118f387SNathan Whitehorn if (is_partition) { 1306f36a5e0fSNathan Whitehorn r = gctl_get_handle(); 1307f36a5e0fSNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 1308f36a5e0fSNathan Whitehorn gctl_ro_param(r, "arg0", -1, geom->lg_name); 1309f36a5e0fSNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 1310f36a5e0fSNathan Whitehorn gctl_issue(r); /* Ignore non-fatal errors */ 1311f36a5e0fSNathan Whitehorn gctl_free(r); 13122118f387SNathan Whitehorn } 13132118f387SNathan Whitehorn } 13142118f387SNathan Whitehorn 13152118f387SNathan Whitehorn /* 13162118f387SNathan Whitehorn * If this is not a partition, see if that is a problem, complain if 13172118f387SNathan Whitehorn * necessary, and return always, since we need not do anything further, 13182118f387SNathan Whitehorn * error or no. 13192118f387SNathan Whitehorn */ 13202118f387SNathan Whitehorn if (!is_partition) { 13212118f387SNathan Whitehorn if (geom == NULL) 13222118f387SNathan Whitehorn dialog_msgbox("Error", 13232118f387SNathan Whitehorn "Only partitions can be deleted.", 0, 0, TRUE); 13242118f387SNathan Whitehorn return; 13252118f387SNathan Whitehorn } 13262118f387SNathan Whitehorn 13272118f387SNathan Whitehorn r = gctl_get_handle(); 13282118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, pp->lg_geom->lg_class->lg_name); 13292118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name); 13302118f387SNathan Whitehorn gctl_ro_param(r, "flags", -1, GPART_FLAGS); 13312118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "delete"); 13322118f387SNathan Whitehorn 13332118f387SNathan Whitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 13342118f387SNathan Whitehorn if (strcmp(gc->lg_name, "index") == 0) { 13352118f387SNathan Whitehorn idx = atoi(gc->lg_val); 13362118f387SNathan Whitehorn gctl_ro_param(r, "index", sizeof(idx), &idx); 13372118f387SNathan Whitehorn break; 13382118f387SNathan Whitehorn } 13392118f387SNathan Whitehorn } 13402118f387SNathan Whitehorn 13412118f387SNathan Whitehorn errstr = gctl_issue(r); 13422118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') { 13432118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 13442118f387SNathan Whitehorn gctl_free(r); 13452118f387SNathan Whitehorn return; 13462118f387SNathan Whitehorn } 13472118f387SNathan Whitehorn 13482118f387SNathan Whitehorn gctl_free(r); 13492118f387SNathan Whitehorn 13502118f387SNathan Whitehorn delete_part_metadata(pp->lg_name); 13512118f387SNathan Whitehorn } 13522118f387SNathan Whitehorn 13532118f387SNathan Whitehorn void 13542118f387SNathan Whitehorn gpart_revert_all(struct gmesh *mesh) 13552118f387SNathan Whitehorn { 13562118f387SNathan Whitehorn struct gclass *classp; 13572118f387SNathan Whitehorn struct gconfig *gc; 13582118f387SNathan Whitehorn struct ggeom *gp; 13592118f387SNathan Whitehorn struct gctl_req *r; 13602118f387SNathan Whitehorn const char *modified; 13612118f387SNathan Whitehorn 13622118f387SNathan Whitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 13632118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") == 0) 13642118f387SNathan Whitehorn break; 13652118f387SNathan Whitehorn } 13662118f387SNathan Whitehorn 13672118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") != 0) { 13682118f387SNathan Whitehorn dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE); 13692118f387SNathan Whitehorn return; 13702118f387SNathan Whitehorn } 13712118f387SNathan Whitehorn 13722118f387SNathan Whitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 13732118f387SNathan Whitehorn modified = "true"; /* XXX: If we don't know (kernel too old), 13742118f387SNathan Whitehorn * assume there are modifications. */ 13752118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 13762118f387SNathan Whitehorn if (strcmp(gc->lg_name, "modified") == 0) { 13772118f387SNathan Whitehorn modified = gc->lg_val; 13782118f387SNathan Whitehorn break; 13792118f387SNathan Whitehorn } 13802118f387SNathan Whitehorn } 13812118f387SNathan Whitehorn 13822118f387SNathan Whitehorn if (strcmp(modified, "false") == 0) 13832118f387SNathan Whitehorn continue; 13842118f387SNathan Whitehorn 13852118f387SNathan Whitehorn r = gctl_get_handle(); 13862118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 13872118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 13882118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "undo"); 13892118f387SNathan Whitehorn 13907899c6c1SNathan Whitehorn gctl_issue(r); 13912118f387SNathan Whitehorn gctl_free(r); 13922118f387SNathan Whitehorn } 13932118f387SNathan Whitehorn } 13942118f387SNathan Whitehorn 13952118f387SNathan Whitehorn void 13962118f387SNathan Whitehorn gpart_commit(struct gmesh *mesh) 13972118f387SNathan Whitehorn { 13982118f387SNathan Whitehorn struct partition_metadata *md; 13992118f387SNathan Whitehorn struct gclass *classp; 14002118f387SNathan Whitehorn struct ggeom *gp; 14012118f387SNathan Whitehorn struct gconfig *gc; 14022118f387SNathan Whitehorn struct gconsumer *cp; 14032118f387SNathan Whitehorn struct gprovider *pp; 14042118f387SNathan Whitehorn struct gctl_req *r; 14052118f387SNathan Whitehorn const char *errstr; 14062118f387SNathan Whitehorn const char *modified; 14076e15678aSNathan Whitehorn const char *rootfs; 14082118f387SNathan Whitehorn 14092118f387SNathan Whitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 14102118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") == 0) 14112118f387SNathan Whitehorn break; 14122118f387SNathan Whitehorn } 14132118f387SNathan Whitehorn 14146e15678aSNathan Whitehorn /* Figure out what filesystem / uses */ 14156e15678aSNathan Whitehorn rootfs = "ufs"; /* Assume ufs if nothing else present */ 14166e15678aSNathan Whitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 14176e15678aSNathan Whitehorn if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) { 14186e15678aSNathan Whitehorn rootfs = md->fstab->fs_vfstype; 14196e15678aSNathan Whitehorn break; 14206e15678aSNathan Whitehorn } 14216e15678aSNathan Whitehorn } 14226e15678aSNathan Whitehorn 14232118f387SNathan Whitehorn if (strcmp(classp->lg_name, "PART") != 0) { 14242118f387SNathan Whitehorn dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE); 14252118f387SNathan Whitehorn return; 14262118f387SNathan Whitehorn } 14272118f387SNathan Whitehorn 14282118f387SNathan Whitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 14292118f387SNathan Whitehorn modified = "true"; /* XXX: If we don't know (kernel too old), 14302118f387SNathan Whitehorn * assume there are modifications. */ 14312118f387SNathan Whitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 14322118f387SNathan Whitehorn if (strcmp(gc->lg_name, "modified") == 0) { 14332118f387SNathan Whitehorn modified = gc->lg_val; 14342118f387SNathan Whitehorn break; 14352118f387SNathan Whitehorn } 14362118f387SNathan Whitehorn } 14372118f387SNathan Whitehorn 14382118f387SNathan Whitehorn if (strcmp(modified, "false") == 0) 14392118f387SNathan Whitehorn continue; 14402118f387SNathan Whitehorn 14412118f387SNathan Whitehorn /* Add bootcode if necessary, before the commit */ 14422118f387SNathan Whitehorn md = get_part_metadata(gp->lg_name, 0); 14432118f387SNathan Whitehorn if (md != NULL && md->bootcode) 14442118f387SNathan Whitehorn gpart_bootcode(gp); 14452118f387SNathan Whitehorn 14462118f387SNathan Whitehorn /* Now install partcode on its partitions, if necessary */ 14472118f387SNathan Whitehorn LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 14482118f387SNathan Whitehorn md = get_part_metadata(pp->lg_name, 0); 14492118f387SNathan Whitehorn if (md == NULL || !md->bootcode) 14502118f387SNathan Whitehorn continue; 14512118f387SNathan Whitehorn 14522118f387SNathan Whitehorn /* Mark this partition active if that's required */ 14532118f387SNathan Whitehorn gpart_activate(pp); 14542118f387SNathan Whitehorn 14552118f387SNathan Whitehorn /* Check if the partition has sub-partitions */ 14562118f387SNathan Whitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 14572118f387SNathan Whitehorn if (strcmp(cp->lg_geom->lg_class->lg_name, 14582118f387SNathan Whitehorn "PART") == 0) 14592118f387SNathan Whitehorn break; 14602118f387SNathan Whitehorn 14612118f387SNathan Whitehorn if (cp == NULL) /* No sub-partitions */ 14626e15678aSNathan Whitehorn gpart_partcode(pp, rootfs); 14632118f387SNathan Whitehorn } 14642118f387SNathan Whitehorn 14652118f387SNathan Whitehorn r = gctl_get_handle(); 14662118f387SNathan Whitehorn gctl_ro_param(r, "class", -1, "PART"); 14672118f387SNathan Whitehorn gctl_ro_param(r, "arg0", -1, gp->lg_name); 14682118f387SNathan Whitehorn gctl_ro_param(r, "verb", -1, "commit"); 14692118f387SNathan Whitehorn 14702118f387SNathan Whitehorn errstr = gctl_issue(r); 14712118f387SNathan Whitehorn if (errstr != NULL && errstr[0] != '\0') 14722118f387SNathan Whitehorn gpart_show_error("Error", NULL, errstr); 14732118f387SNathan Whitehorn gctl_free(r); 14742118f387SNathan Whitehorn } 14752118f387SNathan Whitehorn } 14762118f387SNathan Whitehorn 1477