xref: /freebsd/lib/libgeom/geom_getxml.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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 
337bd4e7b4SPoul-Henning Kamp #include <sys/types.h>
347bd4e7b4SPoul-Henning Kamp #include <sys/sysctl.h>
3539a8d9f3SBenno Rice #include <errno.h>
367bd4e7b4SPoul-Henning Kamp #include <stdlib.h>
377bd4e7b4SPoul-Henning Kamp #include <string.h>
387bd4e7b4SPoul-Henning Kamp #include "libgeom.h"
397bd4e7b4SPoul-Henning Kamp 
4039a8d9f3SBenno Rice /*
4139a8d9f3SBenno Rice  * Amount of extra space we allocate to try and anticipate the size of
4239a8d9f3SBenno Rice  * confxml.
4339a8d9f3SBenno Rice  */
4439a8d9f3SBenno Rice #define	GEOM_GETXML_SLACK	4096
4539a8d9f3SBenno Rice 
4639a8d9f3SBenno Rice /*
4739a8d9f3SBenno Rice  * Number of times to retry in the face of the size of confxml exceeding
4839a8d9f3SBenno Rice  * that of our buffer.
4939a8d9f3SBenno Rice  */
5039a8d9f3SBenno Rice #define	GEOM_GETXML_RETRIES	4
5139a8d9f3SBenno Rice 
527f16b501SAlexander Motin /*
537f16b501SAlexander Motin  * Size of confxml buffer to request via getxml control request.  It is
547f16b501SAlexander Motin  * expected to be sufficient for single geom and its parents.  In case of
557f16b501SAlexander Motin  * overflow fall back to requesting full confxml via sysctl interface.
567f16b501SAlexander Motin  */
577f16b501SAlexander Motin #define	GEOM_GETXML_BUFFER	65536
587f16b501SAlexander Motin 
597bd4e7b4SPoul-Henning Kamp char *
geom_getxml(void)60e17aa6ffSEd Schouten geom_getxml(void)
617bd4e7b4SPoul-Henning Kamp {
627bd4e7b4SPoul-Henning Kamp 	char *p;
637b6942a1SUlf Lilleengen 	size_t l = 0;
647b6942a1SUlf Lilleengen 	int mib[3];
657b6942a1SUlf Lilleengen 	size_t sizep;
6639a8d9f3SBenno Rice 	int retries;
677bd4e7b4SPoul-Henning Kamp 
687b6942a1SUlf Lilleengen 	sizep = sizeof(mib) / sizeof(*mib);
697b6942a1SUlf Lilleengen 	if (sysctlnametomib("kern.geom.confxml", mib, &sizep) != 0)
707b6942a1SUlf Lilleengen 		return (NULL);
717b6942a1SUlf Lilleengen 	if (sysctl(mib, sizep, NULL, &l, NULL, 0) != 0)
727b6942a1SUlf Lilleengen 		return (NULL);
7339a8d9f3SBenno Rice 	l += GEOM_GETXML_SLACK;
7439a8d9f3SBenno Rice 
7539a8d9f3SBenno Rice 	for (retries = 0; retries < GEOM_GETXML_RETRIES; retries++) {
767bd4e7b4SPoul-Henning Kamp 		p = malloc(l);
777b6942a1SUlf Lilleengen 		if (p == NULL)
787b6942a1SUlf Lilleengen 			return (NULL);
7939a8d9f3SBenno Rice 		if (sysctl(mib, sizep, p, &l, NULL, 0) == 0)
807b6942a1SUlf Lilleengen 			return (reallocf(p, strlen(p) + 1));
8139a8d9f3SBenno Rice 
8239a8d9f3SBenno Rice 		free(p);
8339a8d9f3SBenno Rice 
8439a8d9f3SBenno Rice 		if (errno != ENOMEM)
8539a8d9f3SBenno Rice 			return (NULL);
8639a8d9f3SBenno Rice 
8739a8d9f3SBenno Rice 		/*
8839a8d9f3SBenno Rice 		 * Our buffer wasn't big enough. Make it bigger and
8939a8d9f3SBenno Rice 		 * try again.
9039a8d9f3SBenno Rice 		 */
9139a8d9f3SBenno Rice 		l *= 2;
9239a8d9f3SBenno Rice 	}
9339a8d9f3SBenno Rice 
9439a8d9f3SBenno Rice 	return (NULL);
957bd4e7b4SPoul-Henning Kamp }
967f16b501SAlexander Motin 
977f16b501SAlexander Motin char *
geom_getxml_geom(const char * class,const char * geom,int parents)987f16b501SAlexander Motin geom_getxml_geom(const char *class, const char *geom, int parents)
997f16b501SAlexander Motin {
1007f16b501SAlexander Motin 	struct gctl_req *r;
1017f16b501SAlexander Motin 	char *p;
1027f16b501SAlexander Motin 	const char *errstr;
1037f16b501SAlexander Motin 	int nargs = 0;
1047f16b501SAlexander Motin 
1057f16b501SAlexander Motin 	p = malloc(GEOM_GETXML_BUFFER);
1067f16b501SAlexander Motin 	if (p == NULL)
1077f16b501SAlexander Motin 		return (NULL);
1087f16b501SAlexander Motin 	r = gctl_get_handle();
1097f16b501SAlexander Motin 	gctl_ro_param(r, "class", -1, class);
1107f16b501SAlexander Motin 	gctl_ro_param(r, "verb", -1, "getxml");
1117f16b501SAlexander Motin 	gctl_ro_param(r, "parents", sizeof(parents), &parents);
1127f16b501SAlexander Motin 	if (geom) {
1137f16b501SAlexander Motin 		gctl_ro_param(r, "arg0", -1, geom);
1147f16b501SAlexander Motin 		nargs = 1;
1157f16b501SAlexander Motin 	}
1167f16b501SAlexander Motin 	gctl_ro_param(r, "nargs", sizeof(nargs), &nargs);
1177f16b501SAlexander Motin 	p[0] = '\0';
1187f16b501SAlexander Motin 	gctl_add_param(r, "output", GEOM_GETXML_BUFFER, p,
1197f16b501SAlexander Motin 	    GCTL_PARAM_WR | GCTL_PARAM_ASCII);
1207f16b501SAlexander Motin 	errstr = gctl_issue(r);
1217f16b501SAlexander Motin 	if (errstr != NULL && errstr[0] != '\0') {
1227f16b501SAlexander Motin 		gctl_free(r);
1237f16b501SAlexander Motin 		free(p);
1247f16b501SAlexander Motin 		return (geom_getxml());
1257f16b501SAlexander Motin 	}
1267f16b501SAlexander Motin 	gctl_free(r);
1277f16b501SAlexander Motin 	return (p);
1287f16b501SAlexander Motin }
129