Work around some behavior of gpart that I absolutely do not understand in

order to make every operation of the partition editor fully revertable.
Under *no circumstances* will it any longer touch the disks until the user
presses Finish and confirms it.

MFC after:	3 days
This commit is contained in:
Nathan Whitehorn 2011-10-07 01:40:30 +00:00
parent 2b03effa01
commit f36a5e0f34
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=226083
4 changed files with 42 additions and 62 deletions

View File

@ -44,8 +44,8 @@ print_partedit_item(WINDOW *partitions, struct partedit_item *items,
wattrset(partitions, selected ? item_selected_attr : item_attr);
wmove(partitions, y, MARGIN + items[item].indentation*2);
dlg_print_text(partitions, items[item].name, 8, &attr);
wmove(partitions, y, 15);
dlg_print_text(partitions, items[item].name, 10, &attr);
wmove(partitions, y, 17);
wattrset(partitions, item_attr);
humanize_number(sizetext, 7, items[item].size, "B", HN_AUTOSCALE,

View File

@ -365,39 +365,37 @@ gpart_partcode(struct gprovider *pp)
}
void
gpart_destroy(struct ggeom *lg_geom, int force)
gpart_destroy(struct ggeom *lg_geom)
{
struct gprovider *pp;
struct gctl_req *r;
struct gprovider *pp;
const char *errstr;
int force = 1;
/* Begin with the hosing: delete all partitions */
/* Delete all child metadata */
LIST_FOREACH(pp, &lg_geom->lg_provider, lg_provider)
gpart_delete(pp);
/* Revert any local changes to get this geom into a pristine state */
r = gctl_get_handle();
gctl_ro_param(r, "class", -1, "PART");
gctl_ro_param(r, "arg0", -1, lg_geom->lg_name);
gctl_ro_param(r, "verb", -1, "undo");
gctl_issue(r); /* Ignore errors -- these are non-fatal */
gctl_free(r);
/* Now destroy the geom itself */
r = gctl_get_handle();
gctl_ro_param(r, "class", -1, "PART");
gctl_ro_param(r, "arg0", -1, lg_geom->lg_name);
gctl_ro_param(r, "flags", -1, GPART_FLAGS);
gctl_ro_param(r, "force", sizeof(force), &force);
gctl_ro_param(r, "verb", -1, "destroy");
errstr = gctl_issue(r);
if (errstr != NULL && errstr[0] != '\0')
gpart_show_error("Error", NULL, errstr);
gctl_free(r);
/* If asked, commit the change */
if (force) {
r = gctl_get_handle();
gctl_ro_param(r, "class", -1, "PART");
gctl_ro_param(r, "arg0", -1, lg_geom->lg_name);
gctl_ro_param(r, "verb", -1, "commit");
errstr = gctl_issue(r);
if (errstr != NULL && errstr[0] != '\0')
gpart_show_error("Error", NULL, errstr);
gctl_free(r);
}
/* And any metadata associated with the partition scheme itself */
delete_part_metadata(lg_geom->lg_name);
}
@ -439,28 +437,21 @@ gpart_edit(struct gprovider *pp)
geom = NULL;
LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) {
char message[512];
/*
* The PART object is a consumer, so the user wants to
* edit the partition table. gpart doesn't really
* support this, so we have to hose the whole table
* first.
*/
sprintf(message, "Changing the partition scheme on "
"this disk (%s) requires deleting all existing "
"partitions on this drive. This will PERMANENTLY "
"ERASE any data stored here. Are you sure you want "
"to proceed?", cp->lg_geom->lg_name);
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (choice == 1) /* cancel */
/* Check for zombie geoms, treating them as blank */
scheme = NULL;
LIST_FOREACH(gc, &cp->lg_geom->lg_config, lg_config) {
if (strcmp(gc->lg_name, "scheme") == 0) {
scheme = gc->lg_val;
break;
}
}
if (scheme == NULL || strcmp(scheme, "(none)") == 0) {
gpart_partition(cp->lg_geom->lg_name, NULL);
return;
}
/* Destroy the geom and all sub-partitions */
gpart_destroy(cp->lg_geom, 0);
gpart_destroy(cp->lg_geom);
/* Now re-partition and return */
gpart_partition(cp->lg_geom->lg_name, NULL);
@ -1004,7 +995,7 @@ gpart_delete(struct gprovider *pp)
struct gctl_req *r;
const char *errstr;
intmax_t idx;
int choice, is_partition;
int is_partition;
/* Is it a partition? */
is_partition = (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0);
@ -1017,32 +1008,21 @@ gpart_delete(struct gprovider *pp)
break;
}
/* Destroy all consumers */
/* If so, destroy all children */
if (geom != NULL) {
gpart_destroy(geom);
/* If this is a partition, revert it, so it can be deleted */
if (is_partition) {
char message[512];
/*
* We have to actually really delete the sub-partition
* tree so that the consumers will go away and the
* partition can be deleted. Warn the user.
*/
sprintf(message, "Deleting this partition (%s) "
"requires deleting all existing sub-partitions. "
"This will PERMANENTLY ERASE any data stored here "
"and CANNOT BE REVERTED. Are you sure you want to "
"proceed?", cp->lg_geom->lg_name);
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (choice == 1) /* cancel */
return;
r = gctl_get_handle();
gctl_ro_param(r, "class", -1, "PART");
gctl_ro_param(r, "arg0", -1, geom->lg_name);
gctl_ro_param(r, "verb", -1, "undo");
gctl_issue(r); /* Ignore non-fatal errors */
gctl_free(r);
}
gpart_destroy(geom, is_partition);
}
/*
* If this is not a partition, see if that is a problem, complain if
* necessary, and return always, since we need not do anything further,

View File

@ -254,7 +254,7 @@ wizard_partition(struct gmesh *mesh, const char *disk)
if (subchoice != 0)
goto query;
gpart_destroy(gpart, 1);
gpart_destroy(gpart);
gpart_partition(disk, default_scheme());
scheme = default_scheme();
}
@ -267,7 +267,7 @@ wizard_partition(struct gmesh *mesh, const char *disk)
if (choice != 0)
goto query;
gpart_destroy(gpart, 1);
gpart_destroy(gpart);
}
gpart_partition(disk, default_scheme());

View File

@ -58,7 +58,7 @@ int part_wizard(void);
/* gpart operations */
void gpart_delete(struct gprovider *pp);
void gpart_destroy(struct ggeom *lg_geom, int force);
void gpart_destroy(struct ggeom *lg_geom);
void gpart_edit(struct gprovider *pp);
void gpart_create(struct gprovider *pp, char *default_type, char *default_size,
char *default_mountpoint, char **output, int interactive);