Date: Fri, 14 Jan 2011 05:31:51 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r217390 - user/nwhitehorn/bsdinstall/partedit Message-ID: <201101140531.p0E5VpGe076058@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Fri Jan 14 05:31:51 2011 New Revision: 217390 URL: http://svn.freebsd.org/changeset/base/217390 Log: Add a guided partitioning wizard as a replacement for sysinstall's "Auto Defaults" button. On x86, this uses GPT by default for new disks. Default partitioning layout on all systems is the "One Big /" philosophy. Swap is the second partition for now due to boot loader and BIOS limitations -- it may make sense in the future to make it first, so as to allow the data partition to be extended on systems with resizable disks (RAID, VMs). Added: user/nwhitehorn/bsdinstall/partedit/part_wizard.c Modified: user/nwhitehorn/bsdinstall/partedit/Makefile user/nwhitehorn/bsdinstall/partedit/gpart_ops.c user/nwhitehorn/bsdinstall/partedit/partedit.c user/nwhitehorn/bsdinstall/partedit/partedit.h user/nwhitehorn/bsdinstall/partedit/partedit_pc98.c user/nwhitehorn/bsdinstall/partedit/partedit_powerpc.c user/nwhitehorn/bsdinstall/partedit/partedit_sparc64.c user/nwhitehorn/bsdinstall/partedit/partedit_x86.c Modified: user/nwhitehorn/bsdinstall/partedit/Makefile ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/Makefile Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/Makefile Fri Jan 14 05:31:51 2011 (r217390) @@ -15,7 +15,8 @@ PARTEDIT_ARCH= sparc64 PARTEDIT_ARCH= generic .endif -SRCS= diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c +SRCS= diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \ + part_wizard.c WARNS?= 3 NO_MAN= true Modified: user/nwhitehorn/bsdinstall/partedit/gpart_ops.c ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/gpart_ops.c Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/gpart_ops.c Fri Jan 14 05:31:51 2011 (r217390) @@ -37,7 +37,7 @@ gpart_show_error(const char *title, cons dialog_msgbox(title, message, 0, 0, TRUE); } -static int +int gpart_partition(const char *lg_name, const char *scheme) { int cancel, choice; @@ -241,7 +241,7 @@ gpart_partcode(struct gprovider *pp) } } -static void +void gpart_destroy(struct ggeom *lg_geom, int force) { struct gprovider *pp; @@ -518,7 +518,8 @@ set_default_part_metadata(const char *na } void -gpart_create(struct gprovider *pp) +gpart_create(struct gprovider *pp, char *default_type, char *default_size, + char *default_mountpoint, char **partname, int interactive) { struct gctl_req *r; struct gconfig *gc; @@ -546,6 +547,9 @@ gpart_create(struct gprovider *pp) FALSE}, }; + if (partname != NULL) + *partname = NULL; + /* Record sector and stripe sizes */ sector = pp->lg_sectorsize; stripe = pp->lg_stripesize; @@ -635,11 +639,20 @@ gpart_create(struct gprovider *pp) else nitems = 3; -addpartform: - choice = dlg_form("Add Partition", "", 0, 0, 0, nitems, items, &junk); + if (default_type != NULL) + items[0].text = default_type; + if (default_size != NULL) + items[1].text = default_size; + if (default_mountpoint != NULL) + items[2].text = default_mountpoint; - if (choice) /* Cancel pressed */ - return; +addpartform: + if (interactive) { + choice = dlg_form("Add Partition", "", 0, 0, 0, nitems, + items, &junk); + if (choice) /* Cancel pressed */ + return; + } size = maxsize; if (strlen(items[1].text) > 0) { @@ -693,9 +706,13 @@ addpartform: * the user to add one. */ if (strcmp(items[2].text, "/") == 0 && bootpart_size(scheme) > 0) { - choice = dialog_yesno("Boot Partition", "This partition scheme " - "requires a boot partition for the disk to be bootable. " - "Would you like to make one now?", 0, 0); + if (interactive) + choice = dialog_yesno("Boot Partition", + "This partition scheme requires a boot partition " + "for the disk to be bootable. Would you like to " + "make one now?", 0, 0); + else + choice = 0; if (choice == 0) { /* yes */ r = gctl_get_handle(); @@ -759,6 +776,9 @@ addpartform: if (items[i].text_free) free(items[i].text); gctl_free(r); + + if (partname != NULL) + *partname = strdup(strtok(output, " ")); } void Added: user/nwhitehorn/bsdinstall/partedit/part_wizard.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/nwhitehorn/bsdinstall/partedit/part_wizard.c Fri Jan 14 05:31:51 2011 (r217390) @@ -0,0 +1,263 @@ +#include <sys/param.h> +#include <errno.h> +#include <libutil.h> +#include <inttypes.h> + +#include <libgeom.h> +#include <dialog.h> +#include <dlg_keys.h> + +#include "partedit.h" + +#define GPART_FLAGS "x" /* Do not commit changes by default */ + +static char *boot_disk(struct gmesh *mesh); +static char *wizard_partition(struct gmesh *mesh, const char *disk); +static void wizard_makeparts(struct gmesh *mesh, const char *disk); + +int +part_wizard(void) { + int error; + struct gmesh mesh; + char *disk, *schemeroot; + + error = geom_gettree(&mesh); + + dlg_put_backtitle(); + error = geom_gettree(&mesh); + disk = boot_disk(&mesh); + if (disk == NULL) + return (1); + + dlg_clear(); + dlg_put_backtitle(); + schemeroot = wizard_partition(&mesh, disk); + free(disk); + if (schemeroot == NULL) + return (1); + dlg_clear(); + + geom_deletetree(&mesh); + error = geom_gettree(&mesh); + + wizard_makeparts(&mesh, schemeroot); + free(schemeroot); + + geom_deletetree(&mesh); + + return (0); +} + +static char * +boot_disk(struct gmesh *mesh) +{ + struct gclass *classp; + struct ggeom *gp; + struct gprovider *pp; + DIALOG_LISTITEM *disks = NULL; + char diskdesc[512]; + char *chosen; + int i, err, selected, n = 0; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "DISK") != 0 && + strcmp(classp->lg_name, "MD") != 0) + continue; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + if (LIST_EMPTY(&gp->lg_provider)) + continue; + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + disks = realloc(disks, (++n)*sizeof(disks[0])); + disks[n-1].name = pp->lg_name; + humanize_number(diskdesc, 7, pp->lg_mediasize, + "B", HN_AUTOSCALE, HN_DECIMAL); + if (strncmp(pp->lg_name, "ad", 2) == 0) + strcat(diskdesc, " ATA Hard Disk"); + else if (strncmp(pp->lg_name, "da", 2) == 0) + strcat(diskdesc, " SCSI Hard Disk"); + else if (strncmp(pp->lg_name, "md", 2) == 0) + strcat(diskdesc, " Memory Disk"); + else if (strncmp(pp->lg_name, "cd", 2) == 0) { + n--; + continue; + } + disks[n-1].text = strdup(diskdesc); + disks[n-1].help = NULL; + disks[n-1].state = 0; + } + } + } + + if (n > 1) { + err = dlg_menu("Partitioning", + "Select the disk on which to install FreeBSD.", 0, 0, 0, + n, disks, &selected, NULL); + + chosen = (err == 0) ? strdup(disks[selected].name) : NULL; + } else if (n == 1) { + chosen = strdup(disks[0].name); + } else { + chosen = NULL; + } + + for (i = 0; i < n; i++) + free(disks[i].text); + + return (chosen); +} + +static struct gprovider * +provider_for_name(struct gmesh *mesh, const char *name) +{ + struct gclass *classp; + struct gprovider *pp = NULL; + struct ggeom *gp; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + if (strcmp(classp->lg_name, "DISK") != 0 && + strcmp(classp->lg_name, "PART") != 0 && + strcmp(classp->lg_name, "MD") != 0) + continue; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + if (LIST_EMPTY(&gp->lg_provider)) + continue; + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) + if (strcmp(pp->lg_name, name) == 0) + break; + + if (pp != NULL) break; + } + + if (pp != NULL) break; + } + + return (pp); +} + +static char * +wizard_partition(struct gmesh *mesh, const char *disk) +{ + struct gclass *classp; + struct ggeom *gpart = NULL; + struct gconfig *gc; + char message[512]; + const char *scheme; + char *retval = NULL; + int choice; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) + if (strcmp(classp->lg_name, "PART") == 0) + break; + + if (classp != NULL) { + LIST_FOREACH(gpart, &classp->lg_geom, lg_geom) + if (strcmp(gpart->lg_name, disk) == 0) + break; + } + + if (gpart != NULL) { + LIST_FOREACH(gc, &gpart->lg_config, lg_config) { + if (strcmp(gc->lg_name, "scheme") == 0) { + scheme = gc->lg_val; + break; + } + } + } + +query: + dialog_vars.yes_label = "Entire Disk"; + dialog_vars.no_label = "Partition"; + if (gpart != NULL) + dialog_vars.defaultno = TRUE; + + snprintf(message, sizeof(message), "Would you like to use this entire " + "disk (%s) for FreeBSD or partition it to share it with other " + "operating systems? Using the entire disk will erase any data " + "currently stored there.", disk); + choice = dialog_yesno("Partition", message, 0, 0); + + dialog_vars.yes_label = NULL; + dialog_vars.no_label = NULL; + dialog_vars.defaultno = FALSE; + + if (choice == 0) { /* Entire disk */ + if (gpart != NULL) { /* Erase partitioned disk */ + choice = dialog_yesno("Confirmation", "This will erase " + "the disk. Are you sure you want to proceed?", 0, 0); + if (choice != 0) + goto query; + + gpart_destroy(gpart, 1); + } + + gpart_partition(disk, default_scheme()); + scheme = default_scheme(); + } + + if (strcmp(scheme, "PC98") == 0 || strcmp(scheme, "MBR") == 0) { + struct gmesh submesh; + geom_gettree(&submesh); + gpart_create(provider_for_name(&submesh, disk), + "freebsd", NULL, NULL, &retval, choice); + geom_deletetree(&submesh); + } else { + retval = strdup(disk); + } + + return (retval); +} + +static void +wizard_makeparts(struct gmesh *mesh, const char *disk) +{ + struct gmesh submesh; + struct gclass *classp; + struct ggeom *gp; + struct gconfig *gc; + const char *scheme; + struct gprovider *pp; + intmax_t start, end; + intmax_t swapsize; + char swapsizestr[10], rootsizestr[10]; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) + if (strcmp(classp->lg_name, "PART") == 0) + break; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) + if (strcmp(gp->lg_name, disk) == 0) + break; + + LIST_FOREACH(gc, &gp->lg_config, lg_config) { + if (strcmp(gc->lg_name, "first") == 0) + start = strtoimax(gc->lg_val, NULL, 0); + if (strcmp(gc->lg_name, "last") == 0) + end = strtoimax(gc->lg_val, NULL, 0); + if (strcmp(gc->lg_name, "scheme") == 0) + scheme = gc->lg_val; + } + + pp = provider_for_name(mesh, disk); + + swapsize = MIN((end - start)*pp->lg_sectorsize/50, + 4*1024*1024*(intmax_t)(1024)); + humanize_number(swapsizestr, 7, swapsize, "B", HN_AUTOSCALE, + HN_NOSPACE | HN_DECIMAL); + humanize_number(rootsizestr, 7, + (end - start)*pp->lg_sectorsize - swapsize - 1024*1024, + "B", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL); + + geom_gettree(&submesh); + pp = provider_for_name(&submesh, disk); + gpart_create(pp, "freebsd-ufs", rootsizestr, "/", NULL, 0); + geom_deletetree(&submesh); + + geom_gettree(&submesh); + pp = provider_for_name(&submesh, disk); + gpart_create(pp, "freebsd-swap", swapsizestr, NULL, NULL, 0); + geom_deletetree(&submesh); +} Modified: user/nwhitehorn/bsdinstall/partedit/partedit.c ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/partedit.c Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/partedit.c Fri Jan 14 05:31:51 2011 (r217390) @@ -38,6 +38,19 @@ main(void) { dialog_vars.item_help = TRUE; nscroll = i = 0; + /* Ask about guided vs. manual partitioning */ + dlg_put_backtitle(); + dialog_vars.yes_label = "Guided"; + dialog_vars.no_label = "Manual"; + op = dialog_yesno("Partitioning", "Would you like to use the guided " + "partitioning tool (recommended for beginners) or to set up " + "partitions manual (experts)?", 0, 0); + dialog_vars.yes_label = NULL; + dialog_vars.no_label = NULL; + if (op == 0) /* Guided */ + part_wizard(); + + /* Show the part editor either immediately, or to confirm wizard */ while (1) { error = geom_gettree(&mesh); items = read_geom_mesh(&mesh, &nitems); @@ -54,7 +67,8 @@ main(void) { switch (op) { case 0: /* Create */ - gpart_create((struct gprovider *)(items[i].cookie)); + gpart_create((struct gprovider *)(items[i].cookie), + NULL, NULL, NULL, NULL, 1); break; case 1: /* Delete */ gpart_delete((struct gprovider *)(items[i].cookie)); Modified: user/nwhitehorn/bsdinstall/partedit/partedit.h ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/partedit.h Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/partedit.h Fri Jan 14 05:31:51 2011 (r217390) @@ -3,6 +3,7 @@ struct gprovider; struct gmesh; +struct ggeom; TAILQ_HEAD(pmetadata_head, partition_metadata); extern struct pmetadata_head part_metadata; @@ -21,17 +22,23 @@ struct partition_metadata { struct partition_metadata *get_part_metadata(const char *name, int create); void delete_part_metadata(const char *name); +int part_wizard(void); + /* gpart operations */ void gpart_delete(struct gprovider *pp); +void gpart_destroy(struct ggeom *lg_geom, int force); void gpart_edit(struct gprovider *pp); -void gpart_create(struct gprovider *pp); +void gpart_create(struct gprovider *pp, char *default_type, char *default_size, + char *default_mountpoint, char **output, int interactive); void gpart_revert(struct gprovider *pp); void gpart_revert_all(struct gmesh *mesh); void gpart_commit(struct gmesh *mesh); +int gpart_partition(const char *lg_name, const char *scheme); void set_default_part_metadata(const char *name, const char *scheme, const char *type, const char *mountpoint, int newfs); /* machine-dependent bootability checks */ +const char *default_scheme(void); int is_scheme_bootable(const char *part_type); size_t bootpart_size(const char *part_type); const char *bootcode_path(const char *part_type); Modified: user/nwhitehorn/bsdinstall/partedit/partedit_pc98.c ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/partedit_pc98.c Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/partedit_pc98.c Fri Jan 14 05:31:51 2011 (r217390) @@ -2,6 +2,11 @@ #include "partedit.h" +const char * +default_scheme(void) { + return ("PC98"); +} + int is_scheme_bootable(const char *part_type) { if (strcmp(part_type, "PC98") == 0) Modified: user/nwhitehorn/bsdinstall/partedit/partedit_powerpc.c ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/partedit_powerpc.c Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/partedit_powerpc.c Fri Jan 14 05:31:51 2011 (r217390) @@ -2,6 +2,11 @@ #include "partedit.h" +const char * +default_scheme(void) { + return ("APM"); +} + int is_scheme_bootable(const char *part_type) { if (strcmp(part_type, "APM") == 0) Modified: user/nwhitehorn/bsdinstall/partedit/partedit_sparc64.c ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/partedit_sparc64.c Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/partedit_sparc64.c Fri Jan 14 05:31:51 2011 (r217390) @@ -2,6 +2,11 @@ #include "partedit.h" +const char * +default_scheme(void) { + return ("VTOC8"); +} + int is_scheme_bootable(const char *part_type) { if (strcmp(part_type, "VTOC8") == 0) Modified: user/nwhitehorn/bsdinstall/partedit/partedit_x86.c ============================================================================== --- user/nwhitehorn/bsdinstall/partedit/partedit_x86.c Fri Jan 14 05:25:44 2011 (r217389) +++ user/nwhitehorn/bsdinstall/partedit/partedit_x86.c Fri Jan 14 05:31:51 2011 (r217390) @@ -2,6 +2,11 @@ #include "partedit.h" +const char * +default_scheme(void) { + return ("GPT"); +} + int is_scheme_bootable(const char *part_type) { if (strcmp(part_type, "BSD") == 0)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101140531.p0E5VpGe076058>