fetch.c revision 175387
1229997Sken/*- 2229997Sken * Copyright (c) 1980, 1992, 1993 3229997Sken * The Regents of the University of California. All rights reserved. 4232604Strasz * 5229997Sken * Redistribution and use in source and binary forms, with or without 6229997Sken * modification, are permitted provided that the following conditions 7232604Strasz * are met: 8232604Strasz * 1. Redistributions of source code must retain the above copyright 9232604Strasz * notice, this list of conditions and the following disclaimer. 10229997Sken * 2. Redistributions in binary form must reproduce the above copyright 11229997Sken * notice, this list of conditions and the following disclaimer in the 12229997Sken * documentation and/or other materials provided with the distribution. 13229997Sken * 3. All advertising materials mentioning features or use of this software 14229997Sken * must display the following acknowledgement: 15229997Sken * This product includes software developed by the University of 16229997Sken * California, Berkeley and its contributors. 17229997Sken * 4. Neither the name of the University nor the names of its contributors 18229997Sken * may be used to endorse or promote products derived from this software 19229997Sken * without specific prior written permission. 20229997Sken * 21229997Sken * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22229997Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23229997Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24229997Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25229997Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26229997Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27229997Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28229997Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29229997Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30229997Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31229997Sken * SUCH DAMAGE. 32229997Sken */ 33229997Sken 34229997Sken#include <sys/cdefs.h> 35229997Sken 36229997Sken__FBSDID("$FreeBSD: head/usr.bin/systat/fetch.c 175387 2008-01-16 19:27:43Z delphij $"); 37229997Sken 38229997Sken#ifdef lint 39229997Skenstatic const char sccsid[] = "@(#)fetch.c 8.1 (Berkeley) 6/6/93"; 40229997Sken#endif 41229997Sken 42229997Sken#include <sys/types.h> 43229997Sken#include <sys/sysctl.h> 44229997Sken 45229997Sken#include <err.h> 46229997Sken#include <errno.h> 47229997Sken#include <stdlib.h> 48229997Sken#include <string.h> 49229997Sken 50229997Sken#include "systat.h" 51229997Sken#include "extern.h" 52264274Smav 53229997Skenint 54229997Skenkvm_ckread(void *a, void *b, int l) 55229997Sken{ 56229997Sken if (kvm_read(kd, (u_long)a, b, l) != l) { 57229997Sken if (verbose) 58229997Sken error("error reading kmem at %p", a); 59229997Sken return (0); 60229997Sken } 61229997Sken else 62229997Sken return (1); 63229997Sken} 64229997Sken 65229997Skenvoid getsysctl(const char *name, void *ptr, size_t len) 66229997Sken{ 67229997Sken size_t nlen = len; 68229997Sken if (sysctlbyname(name, ptr, &nlen, NULL, 0) != 0) { 69229997Sken error("sysctl(%s...) failed: %s", name, 70229997Sken strerror(errno)); 71275474Smav } 72229997Sken if (nlen != len) { 73229997Sken error("sysctl(%s...) expected %lu, got %lu", name, 74229997Sken (unsigned long)len, (unsigned long)nlen); 75229997Sken } 76229997Sken} 77229997Sken 78229997Sken/* 79229997Sken * Read sysctl data with variable size. Try some times (with increasing 80229997Sken * buffers), fail if still too small. 81229997Sken * This is needed sysctls with possibly raplidly increasing data sizes, 82229997Sken * but imposes little overhead in the case of constant sizes. 83229997Sken * Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds 84229997Sken * the requested data. 85229997Sken * If szp is not NULL, the size of the returned data will be written into *szp. 86229997Sken */ 87229997Sken 88229997Sken/* Some defines: Number of tries. */ 89229997Sken#define SD_NTRIES 10 90229997Sken/* Percent of over-allocation (initial) */ 91229997Sken#define SD_MARGIN 10 92229997Sken/* 93264886Smav * Factor for over-allocation in percent (the margin is increased by this on 94264886Smav * any failed try). 95229997Sken */ 96267537Smav#define SD_FACTOR 50 97267537Smav/* Maximum supported MIB depth */ 98264886Smav#define SD_MAXMIB 16 99267537Smav 100267537Smavchar * 101229997Skensysctl_dynread(const char *n, size_t *szp) 102229997Sken{ 103229997Sken char *rv = NULL; 104229997Sken int mib[SD_MAXMIB]; 105229997Sken size_t mibsz = SD_MAXMIB; 106229997Sken size_t mrg = SD_MARGIN; 107229997Sken size_t sz; 108229997Sken int i; 109267519Smav 110267519Smav /* cache the MIB */ 111267537Smav if (sysctlnametomib(n, mib, &mibsz) == -1) { 112267537Smav if (errno == ENOMEM) { 113267519Smav error("XXX: SD_MAXMIB too small, please bump!"); 114229997Sken } 115229997Sken return NULL; 116229997Sken } 117229997Sken for (i = 0; i < SD_NTRIES; i++) { 118229997Sken /* get needed buffer size */ 119229997Sken if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1) 120229997Sken break; 121229997Sken sz += sz * mrg / 100; 122229997Sken if ((rv = (char *)malloc(sz)) == NULL) { 123229997Sken error("Out of memory!"); 124229997Sken return NULL; 125229997Sken } 126229997Sken if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) { 127229997Sken free(rv); 128229997Sken rv = NULL; 129229997Sken if (errno == ENOMEM) { 130229997Sken mrg += mrg * SD_FACTOR / 100; 131229997Sken } else 132229997Sken break; 133229997Sken } else { 134229997Sken /* success */ 135229997Sken if (szp != NULL) 136229997Sken *szp = sz; 137229997Sken break; 138229997Sken } 139229997Sken } 140229997Sken 141229997Sken return rv; 142229997Sken} 143229997Sken