kvm_file.c revision 194186
1/*- 2 * Copyright (c) 1989, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/lib/libkvm/kvm_file.c 194186 2009-06-14 12:42:06Z ed $"); 32 33#if defined(LIBC_SCCS) && !defined(lint) 34#if 0 35static char sccsid[] = "@(#)kvm_file.c 8.1 (Berkeley) 6/4/93"; 36#endif 37#endif /* LIBC_SCCS and not lint */ 38 39/* 40 * File list interface for kvm. pstat, fstat and netstat are 41 * users of this code, so we've factored it out into a separate module. 42 * Thus, we keep this grunge out of the other kvm applications (i.e., 43 * most other applications are interested only in open/close/read/nlist). 44 */ 45 46#include <sys/param.h> 47#include <sys/user.h> 48#include <sys/proc.h> 49#define _WANT_FILE /* make file.h give us 'struct file' */ 50#include <sys/file.h> 51#include <sys/stat.h> 52#include <sys/ioctl.h> 53#include <nlist.h> 54#include <kvm.h> 55 56#include <vm/vm.h> 57#include <vm/vm_param.h> 58 59#include <sys/sysctl.h> 60 61#include <limits.h> 62#include <ndbm.h> 63#include <paths.h> 64#include <stdlib.h> 65 66#include "kvm_private.h" 67 68#define KREAD(kd, addr, obj) \ 69 (kvm_read(kd, addr, obj, sizeof(*obj)) != sizeof(*obj)) 70 71#define KREADN(kd, addr, obj, cnt) \ 72 (kvm_read(kd, addr, obj, (cnt)) != (cnt)) 73 74/* 75 * Get file structures. 76 */ 77static int 78kvm_deadfiles(kd, op, arg, allproc_o, nprocs) 79 kvm_t *kd; 80 int op, arg, nprocs; 81 long allproc_o; 82{ 83 struct proc proc; 84 struct filedesc filed; 85 int buflen = kd->arglen, ocnt = 0, n = 0, once = 0, i; 86 struct file **ofiles; 87 struct file *fp; 88 struct proc *p; 89 char *where = kd->argspc; 90 91 if (buflen < sizeof (struct file *) + sizeof (struct file)) 92 return (0); 93 if (KREAD(kd, allproc_o, &p)) { 94 _kvm_err(kd, kd->program, "cannot read allproc"); 95 return (0); 96 } 97 for (; p != NULL; p = LIST_NEXT(&proc, p_list)) { 98 if (KREAD(kd, (u_long)p, &proc)) { 99 _kvm_err(kd, kd->program, "can't read proc at %x", p); 100 goto fail; 101 } 102 if (proc.p_state == PRS_NEW) 103 continue; 104 if (proc.p_fd == NULL) 105 continue; 106 if (KREAD(kd, (u_long)p->p_fd, &filed)) { 107 _kvm_err(kd, kd->program, "can't read filedesc at %x", 108 p->p_fd); 109 goto fail; 110 } 111 if (filed.fd_lastfile + 1 > ocnt) { 112 ocnt = filed.fd_lastfile + 1; 113 free(ofiles); 114 ofiles = (struct file **)_kvm_malloc(kd, 115 ocnt * sizeof(struct file *)); 116 if (ofiles == 0) 117 return (0); 118 } 119 if (KREADN(kd, (u_long)filed.fd_ofiles, ofiles, 120 ocnt * sizeof(struct file *))) { 121 _kvm_err(kd, kd->program, "can't read ofiles at %x", 122 filed.fd_ofiles); 123 return (0); 124 } 125 for (i = 0; i <= filed.fd_lastfile; i++) { 126 if ((fp = ofiles[i]) == NULL) 127 continue; 128 /* 129 * copyout filehead (legacy) 130 */ 131 if (!once) { 132 *(struct file **)kd->argspc = fp; 133 *(struct file **)where = fp; 134 buflen -= sizeof (fp); 135 where += sizeof (fp); 136 once = 1; 137 } 138 if (buflen < sizeof (struct file)) 139 goto fail; 140 if (KREAD(kd, (long)fp, ((struct file *)where))) { 141 _kvm_err(kd, kd->program, "can't read kfp"); 142 goto fail; 143 } 144 buflen -= sizeof (struct file); 145 fp = (struct file *)where; 146 where += sizeof (struct file); 147 n++; 148 } 149 } 150 free(ofiles); 151 return (n); 152fail: 153 free(ofiles); 154 return (0); 155 156} 157 158char * 159kvm_getfiles(kd, op, arg, cnt) 160 kvm_t *kd; 161 int op, arg; 162 int *cnt; 163{ 164 int mib[2], st, n, nfiles, nprocs; 165 size_t size; 166 167 _kvm_syserr(kd, kd->program, "kvm_getfiles has been broken for years"); 168 return (0); 169 if (ISALIVE(kd)) { 170 size = 0; 171 mib[0] = CTL_KERN; 172 mib[1] = KERN_FILE; 173 st = sysctl(mib, 2, NULL, &size, NULL, 0); 174 if (st == -1) { 175 _kvm_syserr(kd, kd->program, "kvm_getfiles"); 176 return (0); 177 } 178 if (kd->argspc == 0) 179 kd->argspc = (char *)_kvm_malloc(kd, size); 180 else if (kd->arglen < size) 181 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 182 if (kd->argspc == 0) 183 return (0); 184 kd->arglen = size; 185 st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); 186 if (st != 0) { 187 _kvm_syserr(kd, kd->program, "kvm_getfiles"); 188 return (0); 189 } 190 nfiles = size / sizeof(struct xfile); 191 } else { 192 struct nlist nl[4], *p; 193 194 nl[0].n_name = "_allproc"; 195 nl[1].n_name = "_nprocs"; 196 nl[2].n_name = "_nfiles"; 197 nl[3].n_name = 0; 198 199 if (kvm_nlist(kd, nl) != 0) { 200 for (p = nl; p->n_type != 0; ++p) 201 ; 202 _kvm_err(kd, kd->program, 203 "%s: no such symbol", p->n_name); 204 return (0); 205 } 206 if (KREAD(kd, nl[1].n_value, &nprocs)) { 207 _kvm_err(kd, kd->program, "can't read nprocs"); 208 return (0); 209 } 210 if (KREAD(kd, nl[2].n_value, &nfiles)) { 211 _kvm_err(kd, kd->program, "can't read nfiles"); 212 return (0); 213 } 214 size = sizeof(void *) + (nfiles + 10) * sizeof(struct file); 215 if (kd->argspc == 0) 216 kd->argspc = (char *)_kvm_malloc(kd, size); 217 else if (kd->arglen < size) 218 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 219 if (kd->argspc == 0) 220 return (0); 221 kd->arglen = size; 222 n = kvm_deadfiles(kd, op, arg, nl[0].n_value, nprocs); 223 if (n != nfiles) { 224 _kvm_err(kd, kd->program, "inconsistant nfiles"); 225 return (0); 226 } 227 nfiles = n; 228 } 229 *cnt = nfiles; 230 return (kd->argspc); 231} 232