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