1218799Snwhitehorn/*- 2218799Snwhitehorn * Copyright (c) 2011 Nathan Whitehorn 3218799Snwhitehorn * All rights reserved. 4218799Snwhitehorn * 5218799Snwhitehorn * Redistribution and use in source and binary forms, with or without 6218799Snwhitehorn * modification, are permitted provided that the following conditions 7218799Snwhitehorn * are met: 8218799Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9218799Snwhitehorn * notice, this list of conditions and the following disclaimer. 10218799Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11218799Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12218799Snwhitehorn * documentation and/or other materials provided with the distribution. 13218799Snwhitehorn * 14218799Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15218799Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16218799Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17218799Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18218799Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19218799Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20218799Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21218799Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22218799Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23218799Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24218799Snwhitehorn * SUCH DAMAGE. 25218799Snwhitehorn * 26218799Snwhitehorn * $FreeBSD$ 27218799Snwhitehorn */ 28218799Snwhitehorn 29218799Snwhitehorn#include <sys/param.h> 30218799Snwhitehorn#include <libgen.h> 31218799Snwhitehorn#include <libutil.h> 32218799Snwhitehorn#include <inttypes.h> 33218799Snwhitehorn#include <errno.h> 34218799Snwhitehorn 35218799Snwhitehorn#include <fstab.h> 36218799Snwhitehorn#include <libgeom.h> 37218799Snwhitehorn#include <dialog.h> 38218799Snwhitehorn#include <dlg_keys.h> 39218799Snwhitehorn 40218799Snwhitehorn#include "diskeditor.h" 41218799Snwhitehorn#include "partedit.h" 42218799Snwhitehorn 43218799Snwhitehornstruct pmetadata_head part_metadata; 44244858Snwhitehornstatic int sade_mode = 0; 45218799Snwhitehorn 46218799Snwhitehornstatic int apply_changes(struct gmesh *mesh); 47285769Sallanjudestatic void apply_workaround(struct gmesh *mesh); 48218799Snwhitehornstatic struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems); 49218799Snwhitehornstatic void add_geom_children(struct ggeom *gp, int recurse, 50218799Snwhitehorn struct partedit_item **items, int *nitems); 51218799Snwhitehornstatic void init_fstab_metadata(void); 52218799Snwhitehornstatic void get_mount_points(struct partedit_item *items, int nitems); 53218799Snwhitehornstatic int validate_setup(void); 54218799Snwhitehorn 55225066Snwhitehornstatic void 56225066Snwhitehornsigint_handler(int sig) 57225066Snwhitehorn{ 58225066Snwhitehorn struct gmesh mesh; 59225066Snwhitehorn 60225066Snwhitehorn /* Revert all changes and exit dialog-mode cleanly on SIGINT */ 61225066Snwhitehorn geom_gettree(&mesh); 62225066Snwhitehorn gpart_revert_all(&mesh); 63225066Snwhitehorn geom_deletetree(&mesh); 64225066Snwhitehorn 65225066Snwhitehorn end_dialog(); 66225066Snwhitehorn 67225066Snwhitehorn exit(1); 68225066Snwhitehorn} 69225066Snwhitehorn 70218799Snwhitehornint 71225066Snwhitehornmain(int argc, const char **argv) 72225066Snwhitehorn{ 73218799Snwhitehorn struct partition_metadata *md; 74218799Snwhitehorn const char *prompt; 75226739Snwhitehorn struct partedit_item *items = NULL; 76218799Snwhitehorn struct gmesh mesh; 77218799Snwhitehorn int i, op, nitems, nscroll; 78218799Snwhitehorn int error; 79218799Snwhitehorn 80244858Snwhitehorn if (strcmp(basename(argv[0]), "sade") == 0) 81244858Snwhitehorn sade_mode = 1; 82244858Snwhitehorn 83218799Snwhitehorn TAILQ_INIT(&part_metadata); 84218799Snwhitehorn 85218799Snwhitehorn init_fstab_metadata(); 86218799Snwhitehorn 87218799Snwhitehorn init_dialog(stdin, stdout); 88244858Snwhitehorn if (!sade_mode) 89218799Snwhitehorn dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer"); 90218799Snwhitehorn dialog_vars.item_help = TRUE; 91218799Snwhitehorn nscroll = i = 0; 92218799Snwhitehorn 93225066Snwhitehorn /* Revert changes on SIGINT */ 94225066Snwhitehorn signal(SIGINT, sigint_handler); 95225066Snwhitehorn 96218799Snwhitehorn if (strcmp(basename(argv[0]), "autopart") == 0) { /* Guided */ 97218799Snwhitehorn prompt = "Please review the disk setup. When complete, press " 98225066Snwhitehorn "the Finish button."; 99273831Snwhitehorn /* Experimental ZFS autopartition support */ 100273831Snwhitehorn if (argc > 1 && strcmp(argv[1], "zfs") == 0) { 101273831Snwhitehorn part_wizard("zfs"); 102273831Snwhitehorn } else { 103273831Snwhitehorn part_wizard("ufs"); 104273831Snwhitehorn } 105245700Snwhitehorn } else if (strcmp(basename(argv[0]), "scriptedpart") == 0) { 106245796Snwhitehorn error = scripted_editor(argc, argv); 107245700Snwhitehorn prompt = NULL; 108245796Snwhitehorn if (error != 0) { 109245796Snwhitehorn end_dialog(); 110245796Snwhitehorn return (error); 111245796Snwhitehorn } 112218799Snwhitehorn } else { 113218799Snwhitehorn prompt = "Create partitions for FreeBSD. No changes will be " 114225066Snwhitehorn "made until you select Finish."; 115218799Snwhitehorn } 116218799Snwhitehorn 117218799Snwhitehorn /* Show the part editor either immediately, or to confirm wizard */ 118245700Snwhitehorn while (prompt != NULL) { 119218799Snwhitehorn dlg_clear(); 120218799Snwhitehorn dlg_put_backtitle(); 121218799Snwhitehorn 122226739Snwhitehorn error = geom_gettree(&mesh); 123226739Snwhitehorn if (error == 0) 124226739Snwhitehorn items = read_geom_mesh(&mesh, &nitems); 125226739Snwhitehorn if (error || items == NULL) { 126226739Snwhitehorn dialog_msgbox("Error", "No disks found. If you need to " 127226739Snwhitehorn "install a kernel driver, choose Shell at the " 128226739Snwhitehorn "installation menu.", 0, 0, TRUE); 129226739Snwhitehorn break; 130226739Snwhitehorn } 131226739Snwhitehorn 132226739Snwhitehorn get_mount_points(items, nitems); 133226739Snwhitehorn 134218799Snwhitehorn if (i >= nitems) 135218799Snwhitehorn i = nitems - 1; 136218799Snwhitehorn op = diskeditor_show("Partition Editor", prompt, 137218799Snwhitehorn items, nitems, &i, &nscroll); 138218799Snwhitehorn 139218799Snwhitehorn switch (op) { 140218799Snwhitehorn case 0: /* Create */ 141218799Snwhitehorn gpart_create((struct gprovider *)(items[i].cookie), 142218799Snwhitehorn NULL, NULL, NULL, NULL, 1); 143218799Snwhitehorn break; 144218799Snwhitehorn case 1: /* Delete */ 145218799Snwhitehorn gpart_delete((struct gprovider *)(items[i].cookie)); 146218799Snwhitehorn break; 147218799Snwhitehorn case 2: /* Modify */ 148218799Snwhitehorn gpart_edit((struct gprovider *)(items[i].cookie)); 149218799Snwhitehorn break; 150218799Snwhitehorn case 3: /* Revert */ 151218799Snwhitehorn gpart_revert_all(&mesh); 152218799Snwhitehorn while ((md = TAILQ_FIRST(&part_metadata)) != NULL) { 153218799Snwhitehorn if (md->fstab != NULL) { 154218799Snwhitehorn free(md->fstab->fs_spec); 155218799Snwhitehorn free(md->fstab->fs_file); 156218799Snwhitehorn free(md->fstab->fs_vfstype); 157218799Snwhitehorn free(md->fstab->fs_mntops); 158218799Snwhitehorn free(md->fstab->fs_type); 159218799Snwhitehorn free(md->fstab); 160218799Snwhitehorn } 161218799Snwhitehorn if (md->newfs != NULL) 162218799Snwhitehorn free(md->newfs); 163218799Snwhitehorn free(md->name); 164218799Snwhitehorn 165218799Snwhitehorn TAILQ_REMOVE(&part_metadata, md, metadata); 166218799Snwhitehorn free(md); 167218799Snwhitehorn } 168218799Snwhitehorn init_fstab_metadata(); 169218799Snwhitehorn break; 170218799Snwhitehorn case 4: /* Auto */ 171273831Snwhitehorn part_wizard("ufs"); 172218799Snwhitehorn break; 173218799Snwhitehorn } 174218799Snwhitehorn 175218799Snwhitehorn error = 0; 176219391Snwhitehorn if (op == 5) { /* Finished */ 177225066Snwhitehorn dialog_vars.ok_label = __DECONST(char *, "Commit"); 178225066Snwhitehorn dialog_vars.extra_label = 179225066Snwhitehorn __DECONST(char *, "Revert & Exit"); 180218799Snwhitehorn dialog_vars.extra_button = TRUE; 181225066Snwhitehorn dialog_vars.cancel_label = __DECONST(char *, "Back"); 182218799Snwhitehorn op = dialog_yesno("Confirmation", "Your changes will " 183218799Snwhitehorn "now be written to disk. If you have chosen to " 184218799Snwhitehorn "overwrite existing data, it will be PERMANENTLY " 185225066Snwhitehorn "ERASED. Are you sure you want to commit your " 186225066Snwhitehorn "changes?", 0, 0); 187225066Snwhitehorn dialog_vars.ok_label = NULL; 188218799Snwhitehorn dialog_vars.extra_button = FALSE; 189225066Snwhitehorn dialog_vars.cancel_label = NULL; 190218799Snwhitehorn 191219391Snwhitehorn if (op == 0 && validate_setup()) { /* Save */ 192218799Snwhitehorn error = apply_changes(&mesh); 193285769Sallanjude if (!error) 194285769Sallanjude apply_workaround(&mesh); 195218799Snwhitehorn break; 196225066Snwhitehorn } else if (op == 3) { /* Quit */ 197218799Snwhitehorn gpart_revert_all(&mesh); 198218799Snwhitehorn error = -1; 199218799Snwhitehorn break; 200218799Snwhitehorn } 201218799Snwhitehorn } 202218799Snwhitehorn 203218799Snwhitehorn geom_deletetree(&mesh); 204218799Snwhitehorn free(items); 205218799Snwhitehorn } 206218799Snwhitehorn 207245700Snwhitehorn if (prompt == NULL) { 208245700Snwhitehorn error = geom_gettree(&mesh); 209245700Snwhitehorn if (validate_setup()) { 210245700Snwhitehorn error = apply_changes(&mesh); 211245700Snwhitehorn } else { 212245700Snwhitehorn gpart_revert_all(&mesh); 213245700Snwhitehorn error = -1; 214245700Snwhitehorn } 215245700Snwhitehorn } 216218799Snwhitehorn 217218799Snwhitehorn geom_deletetree(&mesh); 218218799Snwhitehorn free(items); 219218799Snwhitehorn end_dialog(); 220218799Snwhitehorn 221218799Snwhitehorn return (error); 222218799Snwhitehorn} 223218799Snwhitehorn 224218799Snwhitehornstruct partition_metadata * 225218799Snwhitehornget_part_metadata(const char *name, int create) 226218799Snwhitehorn{ 227218799Snwhitehorn struct partition_metadata *md; 228218799Snwhitehorn 229218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) 230218799Snwhitehorn if (md->name != NULL && strcmp(md->name, name) == 0) 231218799Snwhitehorn break; 232218799Snwhitehorn 233218799Snwhitehorn if (md == NULL && create) { 234218799Snwhitehorn md = calloc(1, sizeof(*md)); 235218799Snwhitehorn md->name = strdup(name); 236218799Snwhitehorn TAILQ_INSERT_TAIL(&part_metadata, md, metadata); 237218799Snwhitehorn } 238218799Snwhitehorn 239218799Snwhitehorn return (md); 240218799Snwhitehorn} 241218799Snwhitehorn 242218799Snwhitehornvoid 243225066Snwhitehorndelete_part_metadata(const char *name) 244225066Snwhitehorn{ 245218799Snwhitehorn struct partition_metadata *md; 246218799Snwhitehorn 247218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 248218799Snwhitehorn if (md->name != NULL && strcmp(md->name, name) == 0) { 249218799Snwhitehorn if (md->fstab != NULL) { 250218799Snwhitehorn free(md->fstab->fs_spec); 251218799Snwhitehorn free(md->fstab->fs_file); 252218799Snwhitehorn free(md->fstab->fs_vfstype); 253218799Snwhitehorn free(md->fstab->fs_mntops); 254218799Snwhitehorn free(md->fstab->fs_type); 255218799Snwhitehorn free(md->fstab); 256218799Snwhitehorn } 257218799Snwhitehorn if (md->newfs != NULL) 258218799Snwhitehorn free(md->newfs); 259218799Snwhitehorn free(md->name); 260218799Snwhitehorn 261218799Snwhitehorn TAILQ_REMOVE(&part_metadata, md, metadata); 262218799Snwhitehorn free(md); 263218799Snwhitehorn break; 264218799Snwhitehorn } 265218799Snwhitehorn } 266218799Snwhitehorn} 267218799Snwhitehorn 268218799Snwhitehornstatic int 269218799Snwhitehornvalidate_setup(void) 270218799Snwhitehorn{ 271230309Snwhitehorn struct partition_metadata *md, *root = NULL; 272230309Snwhitehorn int cancel; 273218799Snwhitehorn 274218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 275218799Snwhitehorn if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) 276230309Snwhitehorn root = md; 277218799Snwhitehorn 278218799Snwhitehorn /* XXX: Check for duplicate mountpoints */ 279218799Snwhitehorn } 280218799Snwhitehorn 281230309Snwhitehorn if (root == NULL) { 282218799Snwhitehorn dialog_msgbox("Error", "No root partition was found. " 283218799Snwhitehorn "The root FreeBSD partition must have a mountpoint of '/'.", 284218799Snwhitehorn 0, 0, TRUE); 285218799Snwhitehorn return (FALSE); 286218799Snwhitehorn } 287218799Snwhitehorn 288230309Snwhitehorn /* 289230309Snwhitehorn * Check for root partitions that we aren't formatting, which is 290230309Snwhitehorn * usually a mistake 291230309Snwhitehorn */ 292244858Snwhitehorn if (root->newfs == NULL && !sade_mode) { 293230309Snwhitehorn dialog_vars.defaultno = TRUE; 294230309Snwhitehorn cancel = dialog_yesno("Warning", "The chosen root partition " 295230309Snwhitehorn "has a preexisting filesystem. If it contains an existing " 296230309Snwhitehorn "FreeBSD system, please update it with freebsd-update " 297230309Snwhitehorn "instead of installing a new system on it. The partition " 298230309Snwhitehorn "can also be erased by pressing \"No\" and then deleting " 299230309Snwhitehorn "and recreating it. Are you sure you want to proceed?", 300230309Snwhitehorn 0, 0); 301230309Snwhitehorn dialog_vars.defaultno = FALSE; 302230309Snwhitehorn if (cancel) 303230309Snwhitehorn return (FALSE); 304230309Snwhitehorn } 305230309Snwhitehorn 306218799Snwhitehorn return (TRUE); 307218799Snwhitehorn} 308218799Snwhitehorn 309218799Snwhitehornstatic int 310218799Snwhitehornapply_changes(struct gmesh *mesh) 311218799Snwhitehorn{ 312218799Snwhitehorn struct partition_metadata *md; 313218799Snwhitehorn char message[512]; 314218799Snwhitehorn int i, nitems, error; 315218799Snwhitehorn const char **items; 316218799Snwhitehorn const char *fstab_path; 317218799Snwhitehorn FILE *fstab; 318218799Snwhitehorn 319218799Snwhitehorn nitems = 1; /* Partition table changes */ 320218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 321218799Snwhitehorn if (md->newfs != NULL) 322218799Snwhitehorn nitems++; 323218799Snwhitehorn } 324218799Snwhitehorn items = calloc(nitems * 2, sizeof(const char *)); 325218799Snwhitehorn items[0] = "Writing partition tables"; 326218799Snwhitehorn items[1] = "7"; /* In progress */ 327218799Snwhitehorn i = 1; 328218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 329218799Snwhitehorn if (md->newfs != NULL) { 330218799Snwhitehorn char *item; 331218799Snwhitehorn item = malloc(255); 332218799Snwhitehorn sprintf(item, "Initializing %s", md->name); 333218799Snwhitehorn items[i*2] = item; 334218799Snwhitehorn items[i*2 + 1] = "Pending"; 335218799Snwhitehorn i++; 336218799Snwhitehorn } 337218799Snwhitehorn } 338218799Snwhitehorn 339218799Snwhitehorn i = 0; 340218799Snwhitehorn dialog_mixedgauge("Initializing", 341218799Snwhitehorn "Initializing file systems. Please wait.", 0, 0, i*100/nitems, 342218799Snwhitehorn nitems, __DECONST(char **, items)); 343218799Snwhitehorn gpart_commit(mesh); 344218799Snwhitehorn items[i*2 + 1] = "3"; 345218799Snwhitehorn i++; 346218799Snwhitehorn 347218799Snwhitehorn if (getenv("BSDINSTALL_LOG") == NULL) 348218799Snwhitehorn setenv("BSDINSTALL_LOG", "/dev/null", 1); 349218799Snwhitehorn 350218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 351218799Snwhitehorn if (md->newfs != NULL) { 352218799Snwhitehorn items[i*2 + 1] = "7"; /* In progress */ 353218799Snwhitehorn dialog_mixedgauge("Initializing", 354218799Snwhitehorn "Initializing file systems. Please wait.", 0, 0, 355218799Snwhitehorn i*100/nitems, nitems, __DECONST(char **, items)); 356218799Snwhitehorn sprintf(message, "(echo %s; %s) >>%s 2>>%s", 357218799Snwhitehorn md->newfs, md->newfs, getenv("BSDINSTALL_LOG"), 358218799Snwhitehorn getenv("BSDINSTALL_LOG")); 359218799Snwhitehorn error = system(message); 360218799Snwhitehorn items[i*2 + 1] = (error == 0) ? "3" : "1"; 361218799Snwhitehorn i++; 362218799Snwhitehorn } 363218799Snwhitehorn } 364218799Snwhitehorn dialog_mixedgauge("Initializing", 365218799Snwhitehorn "Initializing file systems. Please wait.", 0, 0, 366218799Snwhitehorn i*100/nitems, nitems, __DECONST(char **, items)); 367218799Snwhitehorn 368218799Snwhitehorn for (i = 1; i < nitems; i++) 369218799Snwhitehorn free(__DECONST(char *, items[i*2])); 370218799Snwhitehorn free(items); 371218799Snwhitehorn 372218799Snwhitehorn if (getenv("PATH_FSTAB") != NULL) 373218799Snwhitehorn fstab_path = getenv("PATH_FSTAB"); 374218799Snwhitehorn else 375218799Snwhitehorn fstab_path = "/etc/fstab"; 376218799Snwhitehorn fstab = fopen(fstab_path, "w+"); 377218799Snwhitehorn if (fstab == NULL) { 378218799Snwhitehorn sprintf(message, "Cannot open fstab file %s for writing (%s)\n", 379218799Snwhitehorn getenv("PATH_FSTAB"), strerror(errno)); 380218799Snwhitehorn dialog_msgbox("Error", message, 0, 0, TRUE); 381218799Snwhitehorn return (-1); 382218799Snwhitehorn } 383218799Snwhitehorn fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n"); 384218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 385218799Snwhitehorn if (md->fstab != NULL) 386223832Skevlo fprintf(fstab, "%s\t%s\t\t%s\t%s\t%d\t%d\n", 387218799Snwhitehorn md->fstab->fs_spec, md->fstab->fs_file, 388218799Snwhitehorn md->fstab->fs_vfstype, md->fstab->fs_mntops, 389218799Snwhitehorn md->fstab->fs_freq, md->fstab->fs_passno); 390218799Snwhitehorn } 391218799Snwhitehorn fclose(fstab); 392218799Snwhitehorn 393218799Snwhitehorn return (0); 394218799Snwhitehorn} 395218799Snwhitehorn 396285769Sallanjudestatic void 397285769Sallanjudeapply_workaround(struct gmesh *mesh) 398285769Sallanjude{ 399285769Sallanjude struct gclass *classp; 400285769Sallanjude struct ggeom *gp; 401285769Sallanjude struct gconfig *gc; 402285769Sallanjude const char *scheme = NULL, *modified = NULL; 403285769Sallanjude 404285769Sallanjude LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 405285769Sallanjude if (strcmp(classp->lg_name, "PART") == 0) 406285769Sallanjude break; 407285769Sallanjude } 408285769Sallanjude 409285769Sallanjude if (strcmp(classp->lg_name, "PART") != 0) { 410285769Sallanjude dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE); 411285769Sallanjude return; 412285769Sallanjude } 413285769Sallanjude 414285769Sallanjude LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 415285769Sallanjude LIST_FOREACH(gc, &gp->lg_config, lg_config) { 416285769Sallanjude if (strcmp(gc->lg_name, "scheme") == 0) { 417285769Sallanjude scheme = gc->lg_val; 418285769Sallanjude } else if (strcmp(gc->lg_name, "modified") == 0) { 419285769Sallanjude modified = gc->lg_val; 420285769Sallanjude } 421285769Sallanjude } 422285769Sallanjude 423285769Sallanjude if (scheme && strcmp(scheme, "GPT") == 0 && 424285769Sallanjude modified && strcmp(modified, "true") == 0) { 425285769Sallanjude if (getenv("WORKAROUND_LENOVO")) 426285769Sallanjude gpart_set_root(gp->lg_name, "lenovofix"); 427285769Sallanjude if (getenv("WORKAROUND_GPTACTIVE")) 428285769Sallanjude gpart_set_root(gp->lg_name, "active"); 429285769Sallanjude } 430285769Sallanjude } 431285769Sallanjude} 432285769Sallanjude 433218799Snwhitehornstatic struct partedit_item * 434225066Snwhitehornread_geom_mesh(struct gmesh *mesh, int *nitems) 435225066Snwhitehorn{ 436218799Snwhitehorn struct gclass *classp; 437218799Snwhitehorn struct ggeom *gp; 438218799Snwhitehorn struct partedit_item *items; 439218799Snwhitehorn 440218799Snwhitehorn *nitems = 0; 441218799Snwhitehorn items = NULL; 442218799Snwhitehorn 443218799Snwhitehorn /* 444218799Snwhitehorn * Build the device table. First add all disks (and CDs). 445218799Snwhitehorn */ 446218799Snwhitehorn 447218799Snwhitehorn LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 448218799Snwhitehorn if (strcmp(classp->lg_name, "DISK") != 0 && 449225066Snwhitehorn strcmp(classp->lg_name, "MD") != 0) 450218799Snwhitehorn continue; 451218799Snwhitehorn 452218799Snwhitehorn /* Now recurse into all children */ 453218799Snwhitehorn LIST_FOREACH(gp, &classp->lg_geom, lg_geom) 454218799Snwhitehorn add_geom_children(gp, 0, &items, nitems); 455218799Snwhitehorn } 456218799Snwhitehorn 457218799Snwhitehorn return (items); 458218799Snwhitehorn} 459218799Snwhitehorn 460218799Snwhitehornstatic void 461218799Snwhitehornadd_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items, 462225066Snwhitehorn int *nitems) 463225066Snwhitehorn{ 464218799Snwhitehorn struct gconsumer *cp; 465218799Snwhitehorn struct gprovider *pp; 466218799Snwhitehorn struct gconfig *gc; 467218799Snwhitehorn 468218799Snwhitehorn if (strcmp(gp->lg_class->lg_name, "PART") == 0 && 469218799Snwhitehorn !LIST_EMPTY(&gp->lg_config)) { 470218799Snwhitehorn LIST_FOREACH(gc, &gp->lg_config, lg_config) { 471218799Snwhitehorn if (strcmp(gc->lg_name, "scheme") == 0) 472218799Snwhitehorn (*items)[*nitems-1].type = gc->lg_val; 473218799Snwhitehorn } 474218799Snwhitehorn } 475218799Snwhitehorn 476218799Snwhitehorn if (LIST_EMPTY(&gp->lg_provider)) 477218799Snwhitehorn return; 478218799Snwhitehorn 479218799Snwhitehorn LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 480218799Snwhitehorn if (strcmp(gp->lg_class->lg_name, "LABEL") == 0) 481218799Snwhitehorn continue; 482218799Snwhitehorn 483218799Snwhitehorn /* Skip WORM media */ 484218799Snwhitehorn if (strncmp(pp->lg_name, "cd", 2) == 0) 485218799Snwhitehorn continue; 486218799Snwhitehorn 487218799Snwhitehorn *items = realloc(*items, 488218799Snwhitehorn (*nitems+1)*sizeof(struct partedit_item)); 489218799Snwhitehorn (*items)[*nitems].indentation = recurse; 490218799Snwhitehorn (*items)[*nitems].name = pp->lg_name; 491218799Snwhitehorn (*items)[*nitems].size = pp->lg_mediasize; 492218799Snwhitehorn (*items)[*nitems].mountpoint = NULL; 493218799Snwhitehorn (*items)[*nitems].type = ""; 494218799Snwhitehorn (*items)[*nitems].cookie = pp; 495218799Snwhitehorn 496218799Snwhitehorn LIST_FOREACH(gc, &pp->lg_config, lg_config) { 497218799Snwhitehorn if (strcmp(gc->lg_name, "type") == 0) 498218799Snwhitehorn (*items)[*nitems].type = gc->lg_val; 499218799Snwhitehorn } 500218799Snwhitehorn 501218799Snwhitehorn /* Skip swap-backed MD devices */ 502218799Snwhitehorn if (strcmp(gp->lg_class->lg_name, "MD") == 0 && 503218799Snwhitehorn strcmp((*items)[*nitems].type, "swap") == 0) 504218799Snwhitehorn continue; 505218799Snwhitehorn 506218799Snwhitehorn (*nitems)++; 507218799Snwhitehorn 508218799Snwhitehorn LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers) 509218799Snwhitehorn add_geom_children(cp->lg_geom, recurse+1, items, 510218799Snwhitehorn nitems); 511218799Snwhitehorn 512218799Snwhitehorn /* Only use first provider for acd */ 513218799Snwhitehorn if (strcmp(gp->lg_class->lg_name, "ACD") == 0) 514218799Snwhitehorn break; 515218799Snwhitehorn } 516218799Snwhitehorn} 517218799Snwhitehorn 518218799Snwhitehornstatic void 519218799Snwhitehorninit_fstab_metadata(void) 520218799Snwhitehorn{ 521218799Snwhitehorn struct fstab *fstab; 522218799Snwhitehorn struct partition_metadata *md; 523218799Snwhitehorn 524218799Snwhitehorn setfsent(); 525218799Snwhitehorn while ((fstab = getfsent()) != NULL) { 526218799Snwhitehorn md = calloc(1, sizeof(struct partition_metadata)); 527218799Snwhitehorn 528218799Snwhitehorn md->name = NULL; 529218799Snwhitehorn if (strncmp(fstab->fs_spec, "/dev/", 5) == 0) 530218799Snwhitehorn md->name = strdup(&fstab->fs_spec[5]); 531218799Snwhitehorn 532218799Snwhitehorn md->fstab = malloc(sizeof(struct fstab)); 533218799Snwhitehorn md->fstab->fs_spec = strdup(fstab->fs_spec); 534218799Snwhitehorn md->fstab->fs_file = strdup(fstab->fs_file); 535218799Snwhitehorn md->fstab->fs_vfstype = strdup(fstab->fs_vfstype); 536218799Snwhitehorn md->fstab->fs_mntops = strdup(fstab->fs_mntops); 537218799Snwhitehorn md->fstab->fs_type = strdup(fstab->fs_type); 538218799Snwhitehorn md->fstab->fs_freq = fstab->fs_freq; 539218799Snwhitehorn md->fstab->fs_passno = fstab->fs_passno; 540218799Snwhitehorn 541218799Snwhitehorn md->newfs = NULL; 542218799Snwhitehorn 543218799Snwhitehorn TAILQ_INSERT_TAIL(&part_metadata, md, metadata); 544218799Snwhitehorn } 545218799Snwhitehorn} 546218799Snwhitehorn 547218799Snwhitehornstatic void 548218799Snwhitehornget_mount_points(struct partedit_item *items, int nitems) 549218799Snwhitehorn{ 550218799Snwhitehorn struct partition_metadata *md; 551218799Snwhitehorn int i; 552218799Snwhitehorn 553218799Snwhitehorn for (i = 0; i < nitems; i++) { 554218799Snwhitehorn TAILQ_FOREACH(md, &part_metadata, metadata) { 555218799Snwhitehorn if (md->name != NULL && md->fstab != NULL && 556218799Snwhitehorn strcmp(md->name, items[i].name) == 0) { 557218799Snwhitehorn items[i].mountpoint = md->fstab->fs_file; 558218799Snwhitehorn break; 559218799Snwhitehorn } 560218799Snwhitehorn } 561218799Snwhitehorn } 562218799Snwhitehorn} 563