xref: /freebsd/lib/libgeom/geom_getxml.c (revision eb8f887758f31f605829c995ce71a627dec0838a)
17bd4e7b4SPoul-Henning Kamp /*-
2*eb8f8877SWarner Losh  * SPDX-License-Identifier: BSD-3-Clause
35e53a4f9SPedro F. Giffuni  *
47bd4e7b4SPoul-Henning Kamp  * Copyright (c) 2003 Poul-Henning Kamp
57bd4e7b4SPoul-Henning Kamp  * All rights reserved.
67f16b501SAlexander Motin  * Copyright (c) 2022 Alexander Motin <mav@FreeBSD.org>
77bd4e7b4SPoul-Henning Kamp  *
87bd4e7b4SPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
97bd4e7b4SPoul-Henning Kamp  * modification, are permitted provided that the following conditions
107bd4e7b4SPoul-Henning Kamp  * are met:
117bd4e7b4SPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
127bd4e7b4SPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
137bd4e7b4SPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
147bd4e7b4SPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
157bd4e7b4SPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
167bd4e7b4SPoul-Henning Kamp  * 3. The names of the authors may not be used to endorse or promote
177bd4e7b4SPoul-Henning Kamp  *    products derived from this software without specific prior written
187bd4e7b4SPoul-Henning Kamp  *    permission.
197bd4e7b4SPoul-Henning Kamp  *
207bd4e7b4SPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
217bd4e7b4SPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227bd4e7b4SPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237bd4e7b4SPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
247bd4e7b4SPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257bd4e7b4SPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267bd4e7b4SPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277bd4e7b4SPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287bd4e7b4SPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297bd4e7b4SPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307bd4e7b4SPoul-Henning Kamp  * SUCH DAMAGE.
317bd4e7b4SPoul-Henning Kamp  *
327bd4e7b4SPoul-Henning Kamp  * $FreeBSD$
337bd4e7b4SPoul-Henning Kamp  */
347bd4e7b4SPoul-Henning Kamp 
357bd4e7b4SPoul-Henning Kamp #include <sys/types.h>
367bd4e7b4SPoul-Henning Kamp #include <sys/sysctl.h>
3739a8d9f3SBenno Rice #include <errno.h>
387bd4e7b4SPoul-Henning Kamp #include <stdlib.h>
397bd4e7b4SPoul-Henning Kamp #include <string.h>
407bd4e7b4SPoul-Henning Kamp #include "libgeom.h"
417bd4e7b4SPoul-Henning Kamp 
4239a8d9f3SBenno Rice /*
4339a8d9f3SBenno Rice  * Amount of extra space we allocate to try and anticipate the size of
4439a8d9f3SBenno Rice  * confxml.
4539a8d9f3SBenno Rice  */
4639a8d9f3SBenno Rice #define	GEOM_GETXML_SLACK	4096
4739a8d9f3SBenno Rice 
4839a8d9f3SBenno Rice /*
4939a8d9f3SBenno Rice  * Number of times to retry in the face of the size of confxml exceeding
5039a8d9f3SBenno Rice  * that of our buffer.
5139a8d9f3SBenno Rice  */
5239a8d9f3SBenno Rice #define	GEOM_GETXML_RETRIES	4
5339a8d9f3SBenno Rice 
547f16b501SAlexander Motin /*
557f16b501SAlexander Motin  * Size of confxml buffer to request via getxml control request.  It is
567f16b501SAlexander Motin  * expected to be sufficient for single geom and its parents.  In case of
577f16b501SAlexander Motin  * overflow fall back to requesting full confxml via sysctl interface.
587f16b501SAlexander Motin  */
597f16b501SAlexander Motin #define	GEOM_GETXML_BUFFER	65536
607f16b501SAlexander Motin 
617bd4e7b4SPoul-Henning Kamp char *
62e17aa6ffSEd Schouten geom_getxml(void)
637bd4e7b4SPoul-Henning Kamp {
647bd4e7b4SPoul-Henning Kamp 	char *p;
657b6942a1SUlf Lilleengen 	size_t l = 0;
667b6942a1SUlf Lilleengen 	int mib[3];
677b6942a1SUlf Lilleengen 	size_t sizep;
6839a8d9f3SBenno Rice 	int retries;
697bd4e7b4SPoul-Henning Kamp 
707b6942a1SUlf Lilleengen 	sizep = sizeof(mib) / sizeof(*mib);
717b6942a1SUlf Lilleengen 	if (sysctlnametomib("kern.geom.confxml", mib, &sizep) != 0)
727b6942a1SUlf Lilleengen 		return (NULL);
737b6942a1SUlf Lilleengen 	if (sysctl(mib, sizep, NULL, &l, NULL, 0) != 0)
747b6942a1SUlf Lilleengen 		return (NULL);
7539a8d9f3SBenno Rice 	l += GEOM_GETXML_SLACK;
7639a8d9f3SBenno Rice 
7739a8d9f3SBenno Rice 	for (retries = 0; retries < GEOM_GETXML_RETRIES; retries++) {
787bd4e7b4SPoul-Henning Kamp 		p = malloc(l);
797b6942a1SUlf Lilleengen 		if (p == NULL)
807b6942a1SUlf Lilleengen 			return (NULL);
8139a8d9f3SBenno Rice 		if (sysctl(mib, sizep, p, &l, NULL, 0) == 0)
827b6942a1SUlf Lilleengen 			return (reallocf(p, strlen(p) + 1));
8339a8d9f3SBenno Rice 
8439a8d9f3SBenno Rice 		free(p);
8539a8d9f3SBenno Rice 
8639a8d9f3SBenno Rice 		if (errno != ENOMEM)
8739a8d9f3SBenno Rice 			return (NULL);
8839a8d9f3SBenno Rice 
8939a8d9f3SBenno Rice 		/*
9039a8d9f3SBenno Rice 		 * Our buffer wasn't big enough. Make it bigger and
9139a8d9f3SBenno Rice 		 * try again.
9239a8d9f3SBenno Rice 		 */
9339a8d9f3SBenno Rice 		l *= 2;
9439a8d9f3SBenno Rice 	}
9539a8d9f3SBenno Rice 
9639a8d9f3SBenno Rice 	return (NULL);
977bd4e7b4SPoul-Henning Kamp }
987f16b501SAlexander Motin 
997f16b501SAlexander Motin char *
1007f16b501SAlexander Motin geom_getxml_geom(const char *class, const char *geom, int parents)
1017f16b501SAlexander Motin {
1027f16b501SAlexander Motin 	struct gctl_req *r;
1037f16b501SAlexander Motin 	char *p;
1047f16b501SAlexander Motin 	const char *errstr;
1057f16b501SAlexander Motin 	int nargs = 0;
1067f16b501SAlexander Motin 
1077f16b501SAlexander Motin 	p = malloc(GEOM_GETXML_BUFFER);
1087f16b501SAlexander Motin 	if (p == NULL)
1097f16b501SAlexander Motin 		return (NULL);
1107f16b501SAlexander Motin 	r = gctl_get_handle();
1117f16b501SAlexander Motin 	gctl_ro_param(r, "class", -1, class);
1127f16b501SAlexander Motin 	gctl_ro_param(r, "verb", -1, "getxml");
1137f16b501SAlexander Motin 	gctl_ro_param(r, "parents", sizeof(parents), &parents);
1147f16b501SAlexander Motin 	if (geom) {
1157f16b501SAlexander Motin 		gctl_ro_param(r, "arg0", -1, geom);
1167f16b501SAlexander Motin 		nargs = 1;
1177f16b501SAlexander Motin 	}
1187f16b501SAlexander Motin 	gctl_ro_param(r, "nargs", sizeof(nargs), &nargs);
1197f16b501SAlexander Motin 	p[0] = '\0';
1207f16b501SAlexander Motin 	gctl_add_param(r, "output", GEOM_GETXML_BUFFER, p,
1217f16b501SAlexander Motin 	    GCTL_PARAM_WR | GCTL_PARAM_ASCII);
1227f16b501SAlexander Motin 	errstr = gctl_issue(r);
1237f16b501SAlexander Motin 	if (errstr != NULL && errstr[0] != '\0') {
1247f16b501SAlexander Motin 		gctl_free(r);
1257f16b501SAlexander Motin 		free(p);
1267f16b501SAlexander Motin 		return (geom_getxml());
1277f16b501SAlexander Motin 	}
1287f16b501SAlexander Motin 	gctl_free(r);
1297f16b501SAlexander Motin 	return (p);
1307f16b501SAlexander Motin }
131