aboutsummaryrefslogtreecommitdiff
path: root/bsdinstall/partedit/partedit.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsdinstall/partedit/partedit.c')
-rw-r--r--bsdinstall/partedit/partedit.c606
1 files changed, 0 insertions, 606 deletions
diff --git a/bsdinstall/partedit/partedit.c b/bsdinstall/partedit/partedit.c
deleted file mode 100644
index df7e573d42c2..000000000000
--- a/bsdinstall/partedit/partedit.c
+++ /dev/null
@@ -1,606 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2011 Nathan Whitehorn
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-
-#include <dialog.h>
-#include <dlg_keys.h>
-#include <err.h>
-#include <errno.h>
-#include <fstab.h>
-#include <inttypes.h>
-#include <libgeom.h>
-#include <libutil.h>
-#include <stdlib.h>
-#include <sysexits.h>
-
-#include "diskmenu.h"
-#include "partedit.h"
-
-struct pmetadata_head part_metadata;
-static int sade_mode = 0;
-
-static int apply_changes(struct gmesh *mesh);
-static void apply_workaround(struct gmesh *mesh);
-static struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems);
-static void add_geom_children(struct ggeom *gp, int recurse,
- struct partedit_item **items, int *nitems);
-static void init_fstab_metadata(void);
-static void get_mount_points(struct partedit_item *items, int nitems);
-static int validate_setup(void);
-
-static void
-sigint_handler(int sig)
-{
- struct gmesh mesh;
-
- /* Revert all changes and exit dialog-mode cleanly on SIGINT */
- geom_gettree(&mesh);
- gpart_revert_all(&mesh);
- geom_deletetree(&mesh);
-
- end_dialog();
-
- exit(1);
-}
-
-int
-main(int argc, const char **argv)
-{
- struct partition_metadata *md;
- const char *progname, *prompt;
- struct partedit_item *items = NULL;
- struct gmesh mesh;
- int i, op, nitems;
- int error;
-
- progname = getprogname();
- if (strcmp(progname, "sade") == 0)
- sade_mode = 1;
-
- TAILQ_INIT(&part_metadata);
-
- init_fstab_metadata();
-
- init_dialog(stdin, stdout);
- if (!sade_mode)
- dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer");
- dialog_vars.item_help = TRUE;
- i = 0;
-
- /* Revert changes on SIGINT */
- signal(SIGINT, sigint_handler);
-
- if (strcmp(progname, "autopart") == 0) { /* Guided */
- prompt = "Please review the disk setup. When complete, press "
- "the Finish button.";
- /* Experimental ZFS autopartition support */
- if (argc > 1 && strcmp(argv[1], "zfs") == 0) {
- part_wizard("zfs");
- } else {
- part_wizard("ufs");
- }
- } else if (strcmp(progname, "scriptedpart") == 0) {
- error = scripted_editor(argc, argv);
- prompt = NULL;
- if (error != 0) {
- end_dialog();
- return (error);
- }
- } else {
- prompt = "Create partitions for FreeBSD. No changes will be "
- "made until you select Finish.";
- }
-
- /* Show the part editor either immediately, or to confirm wizard */
- while (prompt != NULL) {
- dlg_clear();
- dlg_put_backtitle();
-
- error = geom_gettree(&mesh);
- if (error == 0)
- items = read_geom_mesh(&mesh, &nitems);
- if (error || items == NULL) {
- dialog_msgbox("Error", "No disks found. If you need to "
- "install a kernel driver, choose Shell at the "
- "installation menu.", 0, 0, TRUE);
- break;
- }
-
- get_mount_points(items, nitems);
-
- if (i >= nitems)
- i = nitems - 1;
- end_dialog();op = diskmenu_show("Partition Editor", prompt,
- items, nitems, &i);init_dialog(stdin, stdout);
-
- switch (op) {
- case 0: /* Create */
- gpart_create((struct gprovider *)(items[i].cookie),
- NULL, NULL, NULL, NULL, 1);
- break;
- case 1: /* Delete */
- gpart_delete((struct gprovider *)(items[i].cookie));
- break;
- case 2: /* Modify */
- gpart_edit((struct gprovider *)(items[i].cookie));
- break;
- case 3: /* Revert */
- gpart_revert_all(&mesh);
- while ((md = TAILQ_FIRST(&part_metadata)) != NULL) {
- if (md->fstab != NULL) {
- free(md->fstab->fs_spec);
- free(md->fstab->fs_file);
- free(md->fstab->fs_vfstype);
- free(md->fstab->fs_mntops);
- free(md->fstab->fs_type);
- free(md->fstab);
- }
- if (md->newfs != NULL)
- free(md->newfs);
- free(md->name);
-
- TAILQ_REMOVE(&part_metadata, md, metadata);
- free(md);
- }
- init_fstab_metadata();
- break;
- case 4: /* Auto */
- part_wizard("ufs");
- break;
- }
-
- error = 0;
- if (op == 5) { /* Finished */
- dialog_vars.ok_label = __DECONST(char *, "Commit");
- dialog_vars.extra_label =
- __DECONST(char *, "Revert & Exit");
- dialog_vars.extra_button = TRUE;
- dialog_vars.cancel_label = __DECONST(char *, "Back");
- op = dialog_yesno("Confirmation", "Your changes will "
- "now be written to disk. If you have chosen to "
- "overwrite existing data, it will be PERMANENTLY "
- "ERASED. Are you sure you want to commit your "
- "changes?", 0, 0);
- dialog_vars.ok_label = NULL;
- dialog_vars.extra_button = FALSE;
- dialog_vars.cancel_label = NULL;
-
- if (op == 0 && validate_setup()) { /* Save */
- error = apply_changes(&mesh);
- if (!error)
- apply_workaround(&mesh);
- break;
- } else if (op == 3) { /* Quit */
- gpart_revert_all(&mesh);
- error = -1;
- break;
- }
- }
-
- geom_deletetree(&mesh);
- free(items);
- }
-
- if (prompt == NULL) {
- error = geom_gettree(&mesh);
- if (validate_setup()) {
- error = apply_changes(&mesh);
- } else {
- gpart_revert_all(&mesh);
- error = -1;
- }
- }
-
- geom_deletetree(&mesh);
- free(items);
- end_dialog();
-
- return (error);
-}
-
-struct partition_metadata *
-get_part_metadata(const char *name, int create)
-{
- struct partition_metadata *md;
-
- TAILQ_FOREACH(md, &part_metadata, metadata)
- if (md->name != NULL && strcmp(md->name, name) == 0)
- break;
-
- if (md == NULL && create) {
- md = calloc(1, sizeof(*md));
- md->name = strdup(name);
- TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
- }
-
- return (md);
-}
-
-void
-delete_part_metadata(const char *name)
-{
- struct partition_metadata *md;
-
- TAILQ_FOREACH(md, &part_metadata, metadata) {
- if (md->name != NULL && strcmp(md->name, name) == 0) {
- if (md->fstab != NULL) {
- free(md->fstab->fs_spec);
- free(md->fstab->fs_file);
- free(md->fstab->fs_vfstype);
- free(md->fstab->fs_mntops);
- free(md->fstab->fs_type);
- free(md->fstab);
- }
- if (md->newfs != NULL)
- free(md->newfs);
- free(md->name);
-
- TAILQ_REMOVE(&part_metadata, md, metadata);
- free(md);
- break;
- }
- }
-}
-
-static int
-validate_setup(void)
-{
- struct partition_metadata *md, *root = NULL;
- int cancel;
-
- TAILQ_FOREACH(md, &part_metadata, metadata) {
- if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0)
- root = md;
-
- /* XXX: Check for duplicate mountpoints */
- }
-
- if (root == NULL) {
- dialog_msgbox("Error", "No root partition was found. "
- "The root FreeBSD partition must have a mountpoint of '/'.",
- 0, 0, TRUE);
- return (FALSE);
- }
-
- /*
- * Check for root partitions that we aren't formatting, which is
- * usually a mistake
- */
- if (root->newfs == NULL && !sade_mode) {
- dialog_vars.defaultno = TRUE;
- cancel = dialog_yesno("Warning", "The chosen root partition "
- "has a preexisting filesystem. If it contains an existing "
- "FreeBSD system, please update it with freebsd-update "
- "instead of installing a new system on it. The partition "
- "can also be erased by pressing \"No\" and then deleting "
- "and recreating it. Are you sure you want to proceed?",
- 0, 0);
- dialog_vars.defaultno = FALSE;
- if (cancel)
- return (FALSE);
- }
-
- return (TRUE);
-}
-
-static int
-mountpoint_sorter(const void *xa, const void *xb)
-{
- struct partition_metadata *a = *(struct partition_metadata **)xa;
- struct partition_metadata *b = *(struct partition_metadata **)xb;
-
- if (a->fstab == NULL && b->fstab == NULL)
- return 0;
- if (a->fstab == NULL)
- return 1;
- if (b->fstab == NULL)
- return -1;
-
- return strcmp(a->fstab->fs_file, b->fstab->fs_file);
-}
-
-static int
-apply_changes(struct gmesh *mesh)
-{
- struct partition_metadata *md;
- char message[512];
- int i, nitems, error;
- const char **items;
- const char *fstab_path;
- FILE *fstab;
-
- nitems = 1; /* Partition table changes */
- TAILQ_FOREACH(md, &part_metadata, metadata) {
- if (md->newfs != NULL)
- nitems++;
- }
- items = calloc(nitems * 2, sizeof(const char *));
- items[0] = "Writing partition tables";
- items[1] = "7"; /* In progress */
- i = 1;
- TAILQ_FOREACH(md, &part_metadata, metadata) {
- if (md->newfs != NULL) {
- char *item;
- item = malloc(255);
- sprintf(item, "Initializing %s", md->name);
- items[i*2] = item;
- items[i*2 + 1] = "Pending";
- i++;
- }
- }
-
- i = 0;
- dialog_mixedgauge("Initializing",
- "Initializing file systems. Please wait.", 0, 0, i*100/nitems,
- nitems, __DECONST(char **, items));
- gpart_commit(mesh);
- items[i*2 + 1] = "3";
- i++;
-
- if (getenv("BSDINSTALL_LOG") == NULL)
- setenv("BSDINSTALL_LOG", "/dev/null", 1);
-
- TAILQ_FOREACH(md, &part_metadata, metadata) {
- if (md->newfs != NULL) {
- items[i*2 + 1] = "7"; /* In progress */
- dialog_mixedgauge("Initializing",
- "Initializing file systems. Please wait.", 0, 0,
- i*100/nitems, nitems, __DECONST(char **, items));
- sprintf(message, "(echo %s; %s) >>%s 2>>%s",
- md->newfs, md->newfs, getenv("BSDINSTALL_LOG"),
- getenv("BSDINSTALL_LOG"));
- error = system(message);
- items[i*2 + 1] = (error == 0) ? "3" : "1";
- i++;
- }
- }
- dialog_mixedgauge("Initializing",
- "Initializing file systems. Please wait.", 0, 0,
- i*100/nitems, nitems, __DECONST(char **, items));
-
- for (i = 1; i < nitems; i++)
- free(__DECONST(char *, items[i*2]));
- free(items);
-
- /* Sort filesystems for fstab so that mountpoints are ordered */
- {
- struct partition_metadata **tobesorted;
- struct partition_metadata *tmp;
- int nparts = 0;
- TAILQ_FOREACH(md, &part_metadata, metadata)
- nparts++;
- tobesorted = malloc(sizeof(struct partition_metadata *)*nparts);
- nparts = 0;
- TAILQ_FOREACH_SAFE(md, &part_metadata, metadata, tmp) {
- tobesorted[nparts++] = md;
- TAILQ_REMOVE(&part_metadata, md, metadata);
- }
- qsort(tobesorted, nparts, sizeof(tobesorted[0]),
- mountpoint_sorter);
-
- /* Now re-add everything */
- while (nparts-- > 0)
- TAILQ_INSERT_HEAD(&part_metadata,
- tobesorted[nparts], metadata);
- free(tobesorted);
- }
-
- if (getenv("PATH_FSTAB") != NULL)
- fstab_path = getenv("PATH_FSTAB");
- else
- fstab_path = "/etc/fstab";
- fstab = fopen(fstab_path, "w+");
- if (fstab == NULL) {
- sprintf(message, "Cannot open fstab file %s for writing (%s)\n",
- getenv("PATH_FSTAB"), strerror(errno));
- dialog_msgbox("Error", message, 0, 0, TRUE);
- return (-1);
- }
- fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n");
- TAILQ_FOREACH(md, &part_metadata, metadata) {
- if (md->fstab != NULL)
- fprintf(fstab, "%s\t%s\t\t%s\t%s\t%d\t%d\n",
- md->fstab->fs_spec, md->fstab->fs_file,
- md->fstab->fs_vfstype, md->fstab->fs_mntops,
- md->fstab->fs_freq, md->fstab->fs_passno);
- }
- fclose(fstab);
-
- return (0);
-}
-
-static void
-apply_workaround(struct gmesh *mesh)
-{
- struct gclass *classp;
- struct ggeom *gp;
- struct gconfig *gc;
- const char *scheme = NULL, *modified = NULL;
-
- LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
- if (strcmp(classp->lg_name, "PART") == 0)
- break;
- }
-
- if (strcmp(classp->lg_name, "PART") != 0) {
- dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
- return;
- }
-
- LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
- LIST_FOREACH(gc, &gp->lg_config, lg_config) {
- if (strcmp(gc->lg_name, "scheme") == 0) {
- scheme = gc->lg_val;
- } else if (strcmp(gc->lg_name, "modified") == 0) {
- modified = gc->lg_val;
- }
- }
-
- if (scheme && strcmp(scheme, "GPT") == 0 &&
- modified && strcmp(modified, "true") == 0) {
- if (getenv("WORKAROUND_LENOVO"))
- gpart_set_root(gp->lg_name, "lenovofix");
- if (getenv("WORKAROUND_GPTACTIVE"))
- gpart_set_root(gp->lg_name, "active");
- }
- }
-}
-
-static struct partedit_item *
-read_geom_mesh(struct gmesh *mesh, int *nitems)
-{
- struct gclass *classp;
- struct ggeom *gp;
- struct partedit_item *items;
-
- *nitems = 0;
- items = NULL;
-
- /*
- * Build the device table. First add all disks (and CDs).
- */
-
- LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
- if (strcmp(classp->lg_name, "DISK") != 0 &&
- strcmp(classp->lg_name, "MD") != 0)
- continue;
-
- /* Now recurse into all children */
- LIST_FOREACH(gp, &classp->lg_geom, lg_geom)
- add_geom_children(gp, 0, &items, nitems);
- }
-
- return (items);
-}
-
-static void
-add_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items,
- int *nitems)
-{
- struct gconsumer *cp;
- struct gprovider *pp;
- struct gconfig *gc;
-
- if (strcmp(gp->lg_class->lg_name, "PART") == 0 &&
- !LIST_EMPTY(&gp->lg_config)) {
- LIST_FOREACH(gc, &gp->lg_config, lg_config) {
- if (strcmp(gc->lg_name, "scheme") == 0)
- (*items)[*nitems-1].type = gc->lg_val;
- }
- }
-
- if (LIST_EMPTY(&gp->lg_provider))
- return;
-
- LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
- if (strcmp(gp->lg_class->lg_name, "LABEL") == 0)
- continue;
-
- /* Skip WORM media */
- if (strncmp(pp->lg_name, "cd", 2) == 0)
- continue;
-
- *items = realloc(*items,
- (*nitems+1)*sizeof(struct partedit_item));
- (*items)[*nitems].indentation = recurse;
- (*items)[*nitems].name = pp->lg_name;
- (*items)[*nitems].size = pp->lg_mediasize;
- (*items)[*nitems].mountpoint = NULL;
- (*items)[*nitems].type = "";
- (*items)[*nitems].cookie = pp;
-
- LIST_FOREACH(gc, &pp->lg_config, lg_config) {
- if (strcmp(gc->lg_name, "type") == 0)
- (*items)[*nitems].type = gc->lg_val;
- }
-
- /* Skip swap-backed MD devices */
- if (strcmp(gp->lg_class->lg_name, "MD") == 0 &&
- strcmp((*items)[*nitems].type, "swap") == 0)
- continue;
-
- (*nitems)++;
-
- LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
- add_geom_children(cp->lg_geom, recurse+1, items,
- nitems);
-
- /* Only use first provider for acd */
- if (strcmp(gp->lg_class->lg_name, "ACD") == 0)
- break;
- }
-}
-
-static void
-init_fstab_metadata(void)
-{
- struct fstab *fstab;
- struct partition_metadata *md;
-
- setfsent();
- while ((fstab = getfsent()) != NULL) {
- md = calloc(1, sizeof(struct partition_metadata));
-
- md->name = NULL;
- if (strncmp(fstab->fs_spec, "/dev/", 5) == 0)
- md->name = strdup(&fstab->fs_spec[5]);
-
- md->fstab = malloc(sizeof(struct fstab));
- md->fstab->fs_spec = strdup(fstab->fs_spec);
- md->fstab->fs_file = strdup(fstab->fs_file);
- md->fstab->fs_vfstype = strdup(fstab->fs_vfstype);
- md->fstab->fs_mntops = strdup(fstab->fs_mntops);
- md->fstab->fs_type = strdup(fstab->fs_type);
- md->fstab->fs_freq = fstab->fs_freq;
- md->fstab->fs_passno = fstab->fs_passno;
-
- md->newfs = NULL;
-
- TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
- }
-}
-
-static void
-get_mount_points(struct partedit_item *items, int nitems)
-{
- struct partition_metadata *md;
- int i;
-
- for (i = 0; i < nitems; i++) {
- TAILQ_FOREACH(md, &part_metadata, metadata) {
- if (md->name != NULL && md->fstab != NULL &&
- strcmp(md->name, items[i].name) == 0) {
- items[i].mountpoint = md->fstab->fs_file;
- break;
- }
- }
- }
-}