summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/geom/class/part/geom_part.c111
-rw-r--r--sbin/geom/class/part/gpart.85
2 files changed, 102 insertions, 14 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index 1baab4398cef..67d7472a8ef0 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -68,6 +68,7 @@ static char ssize[32];
static const char const bootcode_param[] = "bootcode";
static const char const index_param[] = "index";
static const char const partcode_param[] = "partcode";
+static const char const force_param[] = "force";
static struct gclass *find_class(struct gmesh *, const char *);
static struct ggeom * find_geom(struct gclass *, const char *);
@@ -84,6 +85,8 @@ static void gpart_show_geom(struct ggeom *, const char *);
static int gpart_show_hasopt(struct gctl_req *, const char *, const char *);
static void gpart_write_partcode(struct ggeom *, int, void *, ssize_t);
static void gpart_write_partcode_vtoc8(struct ggeom *, int, void *);
+static void gpart_destroy(struct gctl_req *, unsigned int);
+static void gpart_print_error(const char *);
struct g_command PUBSYM(class_commands)[] = {
{ "add", 0, gpart_issue, {
@@ -118,7 +121,8 @@ struct g_command PUBSYM(class_commands)[] = {
G_OPT_SENTINEL },
"geom", NULL
},
- { "destroy", 0, gpart_issue, {
+ { "destroy", 0, gpart_destroy, {
+ { 'F', force_param, NULL, G_TYPE_BOOL },
{ 'f', "flags", flags, G_TYPE_STRING },
G_OPT_SENTINEL },
"geom", NULL },
@@ -853,10 +857,101 @@ gpart_bootcode(struct gctl_req *req, unsigned int fl)
}
static void
+gpart_destroy(struct gctl_req *req, unsigned int fl)
+{
+ struct gmesh mesh;
+ struct gclass *classp;
+ struct gctl_req *req2;
+ struct ggeom *gp;
+ struct gprovider *pp;
+ const char *s;
+ int error, val;
+
+ if (gctl_has_param(req, force_param)) {
+ val = gctl_get_int(req, force_param);
+ error = gctl_delete_param(req, force_param);
+ if (error)
+ errc(EXIT_FAILURE, error, "internal error");
+ if (val == 0)
+ goto done;
+ s = gctl_get_ascii(req, "class");
+ if (s == NULL)
+ abort();
+ error = geom_gettree(&mesh);
+ if (error != 0)
+ errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
+ classp = find_class(&mesh, s);
+ if (classp == NULL) {
+ geom_deletetree(&mesh);
+ errx(EXIT_FAILURE, "Class %s not found.", s);
+ }
+ s = gctl_get_ascii(req, "geom");
+ if (s == NULL)
+ abort();
+ gp = find_geom(classp, s);
+ if (gp == NULL)
+ errx(EXIT_FAILURE, "No such geom: %s.", s);
+ val = 0;
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider){
+ s = find_provcfg(pp, "index");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Index not found for %s.",
+ pp->lg_name);
+ req2 = gctl_get_handle();
+ gctl_ro_param(req2, "class", -1, classp->lg_name);
+ gctl_ro_param(req2, "geom", -1, gp->lg_name);
+ gctl_ro_param(req2, "verb", -1, "delete");
+ gctl_ro_param(req2, index_param, -1, s);
+ gctl_ro_param(req2, "flags", -1, "X");
+ s = gctl_issue(req2);
+ if (s != NULL && s[0] != '\0') {
+ gpart_print_error(s);
+ gctl_free(req2);
+ if (val) { /* try to undo changes */
+ req2 = gctl_get_handle();
+ gctl_ro_param(req2, "verb", -1,
+ "undo");
+ gctl_ro_param(req2, "class", -1,
+ classp->lg_name);
+ gctl_ro_param(req2, "geom", -1,
+ gp->lg_name);
+ gctl_issue(req2);
+ gctl_free(req2);
+ }
+ geom_deletetree(&mesh);
+ exit(EXIT_FAILURE);
+ }
+ gctl_free(req2);
+ val = 1;
+ }
+ geom_deletetree(&mesh);
+ }
+done:
+ gpart_issue(req, fl);
+}
+
+static void
+gpart_print_error(const char *errstr)
+{
+ char *errmsg;
+ int error;
+
+ error = strtol(errstr, &errmsg, 0);
+ if (errmsg != errstr) {
+ while (errmsg[0] == ' ')
+ errmsg++;
+ if (errmsg[0] != '\0')
+ warnc(error, "%s", errmsg);
+ else
+ warnc(error, NULL);
+ } else
+ warnx("%s", errmsg);
+}
+
+static void
gpart_issue(struct gctl_req *req, unsigned int fl __unused)
{
char buf[4096];
- char *errmsg;
const char *errstr;
int error, status;
@@ -878,17 +973,7 @@ gpart_issue(struct gctl_req *req, unsigned int fl __unused)
goto done;
}
- error = strtol(errstr, &errmsg, 0);
- if (errmsg != errstr) {
- while (errmsg[0] == ' ')
- errmsg++;
- if (errmsg[0] != '\0')
- warnc(error, "%s", errmsg);
- else
- warnc(error, NULL);
- } else
- warnx("%s", errmsg);
-
+ gpart_print_error(errstr);
status = EXIT_FAILURE;
done:
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
index a8ccdd5fc8ad..60fb4632b21e 100644
--- a/sbin/geom/class/part/gpart.8
+++ b/sbin/geom/class/part/gpart.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 27, 2010
+.Dd Sep 24, 2010
.Dt GPART 8
.Os
.Sh NAME
@@ -118,6 +118,7 @@ utility:
.\" ==== DESTROY ====
.Nm
.Cm destroy
+.Op Fl F
.Op Fl f Ar flags
.Ar geom
.\" ==== MODIFY ====
@@ -317,6 +318,8 @@ Destroy the partitioning scheme as implemented by geom
.Pp
Additional options include:
.Bl -tag -width 10n
+.It Fl F
+Forced destroying of the partition table even if it is not empty.
.It Fl f Ar flags
Additional operational flags.
See the section entitled