19b50d902SRodney W. Grimes /*- 29b50d902SRodney W. Grimes * Copyright (c) 1980, 1992, 1993 39b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 49b50d902SRodney W. Grimes * 59b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 69b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 79b50d902SRodney W. Grimes * are met: 89b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 99b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 109b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 129b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 13*fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 149b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 159b50d902SRodney W. Grimes * without specific prior written permission. 169b50d902SRodney W. Grimes * 179b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 189b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 199b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 209b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 219b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 229b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 239b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 259b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 269b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 279b50d902SRodney W. Grimes * SUCH DAMAGE. 289b50d902SRodney W. Grimes */ 299b50d902SRodney W. Grimes 309ff712b0SMark Murray #include <sys/cdefs.h> 319ff712b0SMark Murray 329ff712b0SMark Murray __FBSDID("$FreeBSD$"); 339ff712b0SMark Murray 349ff712b0SMark Murray #ifdef lint 359ff712b0SMark Murray static const char sccsid[] = "@(#)fetch.c 8.1 (Berkeley) 6/6/93"; 369ff712b0SMark Murray #endif 379b50d902SRodney W. Grimes 389b50d902SRodney W. Grimes #include <sys/types.h> 39342e2faaSThomas Moestl #include <sys/sysctl.h> 40342e2faaSThomas Moestl 41821df508SXin LI #include <err.h> 429ff712b0SMark Murray #include <errno.h> 43342e2faaSThomas Moestl #include <stdlib.h> 449ff712b0SMark Murray #include <string.h> 45342e2faaSThomas Moestl 469b50d902SRodney W. Grimes #include "systat.h" 479b50d902SRodney W. Grimes #include "extern.h" 489b50d902SRodney W. Grimes 499b50d902SRodney W. Grimes int 5093b9f504SXin LI kvm_ckread(void *a, void *b, int l) 519b50d902SRodney W. Grimes { 529b50d902SRodney W. Grimes if (kvm_read(kd, (u_long)a, b, l) != l) { 539b50d902SRodney W. Grimes if (verbose) 549ff712b0SMark Murray error("error reading kmem at %p", a); 559b50d902SRodney W. Grimes return (0); 569b50d902SRodney W. Grimes } 579b50d902SRodney W. Grimes else 589b50d902SRodney W. Grimes return (1); 599b50d902SRodney W. Grimes } 60342e2faaSThomas Moestl 6193b9f504SXin LI void getsysctl(const char *name, void *ptr, size_t len) 62342e2faaSThomas Moestl { 63342e2faaSThomas Moestl size_t nlen = len; 649ff712b0SMark Murray if (sysctlbyname(name, ptr, &nlen, NULL, 0) != 0) { 65342e2faaSThomas Moestl error("sysctl(%s...) failed: %s", name, 66342e2faaSThomas Moestl strerror(errno)); 67342e2faaSThomas Moestl } 68342e2faaSThomas Moestl if (nlen != len) { 69d62de5c4SThomas Moestl error("sysctl(%s...) expected %lu, got %lu", name, 70d62de5c4SThomas Moestl (unsigned long)len, (unsigned long)nlen); 71342e2faaSThomas Moestl } 72342e2faaSThomas Moestl } 73342e2faaSThomas Moestl 74342e2faaSThomas Moestl /* 75342e2faaSThomas Moestl * Read sysctl data with variable size. Try some times (with increasing 76342e2faaSThomas Moestl * buffers), fail if still too small. 77342e2faaSThomas Moestl * This is needed sysctls with possibly raplidly increasing data sizes, 78342e2faaSThomas Moestl * but imposes little overhead in the case of constant sizes. 79342e2faaSThomas Moestl * Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds 80342e2faaSThomas Moestl * the requested data. 81342e2faaSThomas Moestl * If szp is not NULL, the size of the returned data will be written into *szp. 82342e2faaSThomas Moestl */ 83342e2faaSThomas Moestl 84342e2faaSThomas Moestl /* Some defines: Number of tries. */ 85342e2faaSThomas Moestl #define SD_NTRIES 10 86342e2faaSThomas Moestl /* Percent of over-allocation (initial) */ 87342e2faaSThomas Moestl #define SD_MARGIN 10 88342e2faaSThomas Moestl /* 89342e2faaSThomas Moestl * Factor for over-allocation in percent (the margin is increased by this on 90342e2faaSThomas Moestl * any failed try). 91342e2faaSThomas Moestl */ 92342e2faaSThomas Moestl #define SD_FACTOR 50 93342e2faaSThomas Moestl /* Maximum supported MIB depth */ 94342e2faaSThomas Moestl #define SD_MAXMIB 16 95342e2faaSThomas Moestl 96342e2faaSThomas Moestl char * 9793b9f504SXin LI sysctl_dynread(const char *n, size_t *szp) 98342e2faaSThomas Moestl { 99342e2faaSThomas Moestl char *rv = NULL; 100342e2faaSThomas Moestl int mib[SD_MAXMIB]; 101342e2faaSThomas Moestl size_t mibsz = SD_MAXMIB; 102342e2faaSThomas Moestl size_t mrg = SD_MARGIN; 103342e2faaSThomas Moestl size_t sz; 104342e2faaSThomas Moestl int i; 105342e2faaSThomas Moestl 106342e2faaSThomas Moestl /* cache the MIB */ 107342e2faaSThomas Moestl if (sysctlnametomib(n, mib, &mibsz) == -1) { 108342e2faaSThomas Moestl if (errno == ENOMEM) { 109342e2faaSThomas Moestl error("XXX: SD_MAXMIB too small, please bump!"); 110342e2faaSThomas Moestl } 111342e2faaSThomas Moestl return NULL; 112342e2faaSThomas Moestl } 113342e2faaSThomas Moestl for (i = 0; i < SD_NTRIES; i++) { 114342e2faaSThomas Moestl /* get needed buffer size */ 115342e2faaSThomas Moestl if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1) 116342e2faaSThomas Moestl break; 117342e2faaSThomas Moestl sz += sz * mrg / 100; 118342e2faaSThomas Moestl if ((rv = (char *)malloc(sz)) == NULL) { 119342e2faaSThomas Moestl error("Out of memory!"); 120342e2faaSThomas Moestl return NULL; 121342e2faaSThomas Moestl } 122342e2faaSThomas Moestl if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) { 123342e2faaSThomas Moestl free(rv); 124342e2faaSThomas Moestl rv = NULL; 125342e2faaSThomas Moestl if (errno == ENOMEM) { 126342e2faaSThomas Moestl mrg += mrg * SD_FACTOR / 100; 127342e2faaSThomas Moestl } else 128342e2faaSThomas Moestl break; 129342e2faaSThomas Moestl } else { 130342e2faaSThomas Moestl /* success */ 131342e2faaSThomas Moestl if (szp != NULL) 132342e2faaSThomas Moestl *szp = sz; 133342e2faaSThomas Moestl break; 134342e2faaSThomas Moestl } 135342e2faaSThomas Moestl } 136342e2faaSThomas Moestl 137342e2faaSThomas Moestl return rv; 138342e2faaSThomas Moestl } 139