svn commit: r217390 - user/nwhitehorn/bsdinstall/partedit
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Fri Jan 14 05:31:51 UTC 2011
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)
More information about the svn-src-user
mailing list