1110603Sphk/*-
2110603Sphk * Copyright (c) 2003 Poul-Henning Kamp
3110603Sphk * All rights reserved.
4110603Sphk *
5110603Sphk * Redistribution and use in source and binary forms, with or without
6110603Sphk * modification, are permitted provided that the following conditions
7110603Sphk * are met:
8110603Sphk * 1. Redistributions of source code must retain the above copyright
9110603Sphk *    notice, this list of conditions and the following disclaimer.
10110603Sphk * 2. Redistributions in binary form must reproduce the above copyright
11110603Sphk *    notice, this list of conditions and the following disclaimer in the
12110603Sphk *    documentation and/or other materials provided with the distribution.
13110603Sphk * 3. The names of the authors may not be used to endorse or promote
14110603Sphk *    products derived from this software without specific prior written
15110603Sphk *    permission.
16110603Sphk *
17110603Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18110603Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19110603Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20110603Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21110603Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22110603Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23110603Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24110603Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25110603Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26110603Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27110603Sphk * SUCH DAMAGE.
28110603Sphk *
29110603Sphk * $FreeBSD$
30110603Sphk */
31110603Sphk
32110603Sphk#include <sys/types.h>
33110603Sphk#include <sys/sysctl.h>
34271085Sbenno#include <errno.h>
35110603Sphk#include <stdlib.h>
36110603Sphk#include <string.h>
37110603Sphk#include "libgeom.h"
38110603Sphk
39271085Sbenno/*
40271085Sbenno * Amount of extra space we allocate to try and anticipate the size of
41271085Sbenno * confxml.
42271085Sbenno */
43271085Sbenno#define	GEOM_GETXML_SLACK	4096
44271085Sbenno
45271085Sbenno/*
46271085Sbenno * Number of times to retry in the face of the size of confxml exceeding
47271085Sbenno * that of our buffer.
48271085Sbenno */
49271085Sbenno#define	GEOM_GETXML_RETRIES	4
50271085Sbenno
51110603Sphkchar *
52201320Sedgeom_getxml(void)
53110603Sphk{
54110603Sphk	char *p;
55180369Slulf	size_t l = 0;
56180369Slulf	int mib[3];
57180369Slulf	size_t sizep;
58271085Sbenno	int retries;
59110603Sphk
60180369Slulf	sizep = sizeof(mib) / sizeof(*mib);
61180369Slulf	if (sysctlnametomib("kern.geom.confxml", mib, &sizep) != 0)
62180369Slulf		return (NULL);
63180369Slulf	if (sysctl(mib, sizep, NULL, &l, NULL, 0) != 0)
64180369Slulf		return (NULL);
65271085Sbenno	l += GEOM_GETXML_SLACK;
66271085Sbenno
67271085Sbenno	for (retries = 0; retries < GEOM_GETXML_RETRIES; retries++) {
68271085Sbenno		p = malloc(l);
69271085Sbenno		if (p == NULL)
70271085Sbenno			return (NULL);
71271085Sbenno		if (sysctl(mib, sizep, p, &l, NULL, 0) == 0)
72271085Sbenno			return (reallocf(p, strlen(p) + 1));
73271085Sbenno
74110603Sphk		free(p);
75271085Sbenno
76271085Sbenno		if (errno != ENOMEM)
77271085Sbenno			return (NULL);
78271085Sbenno
79271085Sbenno		/*
80271085Sbenno		 * Our buffer wasn't big enough. Make it bigger and
81271085Sbenno		 * try again.
82271085Sbenno		 */
83271085Sbenno		l *= 2;
84110603Sphk	}
85271085Sbenno
86271085Sbenno	return (NULL);
87110603Sphk}
88