kvm_file.c revision 17141
1117610Sdes/*- 2174832Sdes * Copyright (c) 1989, 1992, 1993 3117610Sdes * The Regents of the University of California. All rights reserved. 4174832Sdes * 5117610Sdes * Redistribution and use in source and binary forms, with or without 6174832Sdes * modification, are permitted provided that the following conditions 7117610Sdes * are met: 8174832Sdes * 1. Redistributions of source code must retain the above copyright 9174832Sdes * notice, this list of conditions and the following disclaimer. 10117610Sdes * 2. Redistributions in binary form must reproduce the above copyright 11117610Sdes * notice, this list of conditions and the following disclaimer in the 12117610Sdes * documentation and/or other materials provided with the distribution. 13117610Sdes * 3. All advertising materials mentioning features or use of this software 14117610Sdes * must display the following acknowledgement: 15117610Sdes * This product includes software developed by the University of 16174832Sdes * California, Berkeley and its contributors. 17174832Sdes * 4. Neither the name of the University nor the names of its contributors 18117610Sdes * may be used to endorse or promote products derived from this software 19117610Sdes * without specific prior written permission. 20117610Sdes * 21141098Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22141098Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23141098Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24174832Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25174832Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26174832Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27174832Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28174832Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29174832Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30117610Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31117610Sdes * SUCH DAMAGE. 32174832Sdes */ 33174832Sdes 34174832Sdes#if defined(LIBC_SCCS) && !defined(lint) 35174832Sdesstatic char sccsid[] = "@(#)kvm_file.c 8.1 (Berkeley) 6/4/93"; 36174832Sdes#endif /* LIBC_SCCS and not lint */ 37174832Sdes 38174832Sdes/* 39174832Sdes * File list interface for kvm. pstat, fstat and netstat are 40174832Sdes * users of this code, so we've factored it out into a separate module. 41174832Sdes * Thus, we keep this grunge out of the other kvm applications (i.e., 42174832Sdes * most other applications are interested only in open/close/read/nlist). 43174832Sdes */ 44174832Sdes 45174832Sdes#include <sys/param.h> 46174832Sdes#include <sys/user.h> 47174832Sdes#include <sys/proc.h> 48174832Sdes#define KERNEL 49174832Sdes#include <sys/file.h> 50174832Sdes#undef KERNEL 51174832Sdes#include <sys/stat.h> 52174832Sdes#include <sys/ioctl.h> 53174832Sdes#include <nlist.h> 54174832Sdes#include <kvm.h> 55174832Sdes 56117610Sdes#include <vm/vm.h> 57141098Sdes#include <vm/vm_param.h> 58117610Sdes#include <vm/swap_pager.h> 59117610Sdes 60117610Sdes#include <sys/sysctl.h> 61117610Sdes 62117610Sdes#include <limits.h> 63117610Sdes#include <ndbm.h> 64174832Sdes#include <paths.h> 65174832Sdes 66174832Sdes#include "kvm_private.h" 67174832Sdes 68174832Sdes#define KREAD(kd, addr, obj) \ 69174832Sdes (kvm_read(kd, addr, obj, sizeof(*obj)) != sizeof(*obj)) 70174832Sdes 71174832Sdes/* 72174832Sdes * Get file structures. 73174832Sdes */ 74174832Sdesstatic int 75174832Sdeskvm_deadfiles(kd, op, arg, filehead_o, nfiles) 76174832Sdes kvm_t *kd; 77174832Sdes int op, arg, nfiles; 78174832Sdes long filehead_o; 79174832Sdes{ 80174832Sdes int buflen = kd->arglen, n = 0; 81174832Sdes struct file *fp; 82174832Sdes register char *where = kd->argspc; 83174832Sdes struct filelist filehead; 84174832Sdes 85174832Sdes /* 86174832Sdes * first copyout filehead 87174832Sdes */ 88174832Sdes if (buflen > sizeof (filehead)) { 89174832Sdes if (KREAD(kd, filehead_o, &filehead)) { 90174832Sdes _kvm_err(kd, kd->program, "can't read filehead"); 91174832Sdes return (0); 92174832Sdes } 93174832Sdes buflen -= sizeof (filehead); 94174832Sdes where += sizeof (filehead); 95174832Sdes *(struct filelist *)kd->argspc = filehead; 96174832Sdes } 97141098Sdes /* 98174832Sdes * followed by an array of file structures 99174832Sdes */ 100174832Sdes for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) { 101141098Sdes if (buflen > sizeof (struct file)) { 102141098Sdes if (KREAD(kd, (long)fp, ((struct file *)where))) { 103141098Sdes _kvm_err(kd, kd->program, "can't read kfp"); 104117610Sdes return (0); 105141098Sdes } 106141098Sdes buflen -= sizeof (struct file); 107141098Sdes fp = (struct file *)where; 108141098Sdes where += sizeof (struct file); 109141098Sdes n++; 110141098Sdes } 111141098Sdes } 112141098Sdes if (n != nfiles) { 113141098Sdes _kvm_err(kd, kd->program, "inconsistant nfiles"); 114174832Sdes return (0); 115141098Sdes } 116141098Sdes return (nfiles); 117141098Sdes} 118141098Sdes 119174832Sdeschar * 120174832Sdeskvm_getfiles(kd, op, arg, cnt) 121141098Sdes kvm_t *kd; 122141098Sdes int op, arg; 123141098Sdes int *cnt; 124141098Sdes{ 125141098Sdes int mib[2], size, st, nfiles; 126174832Sdes struct file *fp, *fplim; 127141098Sdes struct filelist filehead; 128141098Sdes 129141098Sdes if (ISALIVE(kd)) { 130141098Sdes size = 0; 131141098Sdes mib[0] = CTL_KERN; 132141098Sdes mib[1] = KERN_FILE; 133117610Sdes st = sysctl(mib, 2, NULL, &size, NULL, 0); 134174832Sdes if (st == -1) { 135117610Sdes _kvm_syserr(kd, kd->program, "kvm_getprocs"); 136117610Sdes return (0); 137174832Sdes } 138117610Sdes if (kd->argspc == 0) 139174832Sdes kd->argspc = (char *)_kvm_malloc(kd, size); 140174832Sdes else if (kd->arglen < size) 141174832Sdes kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 142174832Sdes if (kd->argspc == 0) 143174832Sdes return (0); 144174832Sdes kd->arglen = size; 145174832Sdes st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); 146174832Sdes if (st == -1 || size < sizeof(filehead)) { 147174832Sdes _kvm_syserr(kd, kd->program, "kvm_getfiles"); 148174832Sdes return (0); 149174832Sdes } 150174832Sdes filehead = *(struct filelist *)kd->argspc; 151174832Sdes fp = (struct file *)(kd->argspc + sizeof (filehead)); 152117610Sdes fplim = (struct file *)(kd->argspc + size); 153174832Sdes for (nfiles = 0; filehead.lh_first && (fp < fplim); nfiles++, fp++) 154174832Sdes filehead.lh_first = fp->f_list.le_next; 155141098Sdes } else { 156117610Sdes struct nlist nl[3], *p; 157174832Sdes 158174832Sdes nl[0].n_name = "_filehead"; 159174832Sdes nl[1].n_name = "_nfiles"; 160174832Sdes nl[2].n_name = 0; 161174832Sdes 162117610Sdes if (kvm_nlist(kd, nl) != 0) { 163117610Sdes for (p = nl; p->n_type != 0; ++p) 164174832Sdes ; 165174832Sdes _kvm_err(kd, kd->program, 166174832Sdes "%s: no such symbol", p->n_name); 167174832Sdes return (0); 168174832Sdes } 169174832Sdes if (KREAD(kd, nl[0].n_value, &nfiles)) { 170174832Sdes _kvm_err(kd, kd->program, "can't read nfiles"); 171174832Sdes return (0); 172174832Sdes } 173174832Sdes size = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 174174832Sdes if (kd->argspc == 0) 175174832Sdes kd->argspc = (char *)_kvm_malloc(kd, size); 176174832Sdes else if (kd->arglen < size) 177174832Sdes kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 178174832Sdes if (kd->argspc == 0) 179174832Sdes return (0); 180117610Sdes kd->arglen = size; 181174832Sdes nfiles = kvm_deadfiles(kd, op, arg, nl[1].n_value, nfiles); 182174832Sdes if (nfiles == 0) 183174832Sdes return (0); 184174832Sdes } 185174832Sdes *cnt = nfiles; 186174832Sdes return (kd->argspc); 187174832Sdes} 188117610Sdes