kvm_file.c revision 194186
11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1989, 1992, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer. 101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer in the 121573Srgrimes * documentation and/or other materials provided with the distribution. 131573Srgrimes * 4. Neither the name of the University nor the names of its contributors 141573Srgrimes * may be used to endorse or promote products derived from this software 151573Srgrimes * without specific prior written permission. 161573Srgrimes * 171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271573Srgrimes * SUCH DAMAGE. 281573Srgrimes */ 291573Srgrimes 3083551Sdillon#include <sys/cdefs.h> 3183551Sdillon__FBSDID("$FreeBSD: head/lib/libkvm/kvm_file.c 194186 2009-06-14 12:42:06Z ed $"); 3283551Sdillon 331573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 3455127Speter#if 0 351573Srgrimesstatic char sccsid[] = "@(#)kvm_file.c 8.1 (Berkeley) 6/4/93"; 3655127Speter#endif 371573Srgrimes#endif /* LIBC_SCCS and not lint */ 381573Srgrimes 391573Srgrimes/* 408870Srgrimes * File list interface for kvm. pstat, fstat and netstat are 411573Srgrimes * users of this code, so we've factored it out into a separate module. 421573Srgrimes * Thus, we keep this grunge out of the other kvm applications (i.e., 431573Srgrimes * most other applications are interested only in open/close/read/nlist). 441573Srgrimes */ 451573Srgrimes 461573Srgrimes#include <sys/param.h> 471573Srgrimes#include <sys/user.h> 481573Srgrimes#include <sys/proc.h> 49179320Spjd#define _WANT_FILE /* make file.h give us 'struct file' */ 501573Srgrimes#include <sys/file.h> 511573Srgrimes#include <sys/stat.h> 521573Srgrimes#include <sys/ioctl.h> 531573Srgrimes#include <nlist.h> 541573Srgrimes#include <kvm.h> 551573Srgrimes 561573Srgrimes#include <vm/vm.h> 571573Srgrimes#include <vm/vm_param.h> 581573Srgrimes 591573Srgrimes#include <sys/sysctl.h> 601573Srgrimes 611573Srgrimes#include <limits.h> 621573Srgrimes#include <ndbm.h> 631573Srgrimes#include <paths.h> 64194186Sed#include <stdlib.h> 651573Srgrimes 661573Srgrimes#include "kvm_private.h" 671573Srgrimes 681573Srgrimes#define KREAD(kd, addr, obj) \ 691573Srgrimes (kvm_read(kd, addr, obj, sizeof(*obj)) != sizeof(*obj)) 701573Srgrimes 71174989Sjeff#define KREADN(kd, addr, obj, cnt) \ 72174989Sjeff (kvm_read(kd, addr, obj, (cnt)) != (cnt)) 73174989Sjeff 741573Srgrimes/* 751573Srgrimes * Get file structures. 761573Srgrimes */ 7717141Sjkhstatic int 78174989Sjeffkvm_deadfiles(kd, op, arg, allproc_o, nprocs) 791573Srgrimes kvm_t *kd; 80174989Sjeff int op, arg, nprocs; 81174989Sjeff long allproc_o; 821573Srgrimes{ 83174989Sjeff struct proc proc; 84174989Sjeff struct filedesc filed; 85174989Sjeff int buflen = kd->arglen, ocnt = 0, n = 0, once = 0, i; 86174989Sjeff struct file **ofiles; 8714523Shsu struct file *fp; 88174989Sjeff struct proc *p; 8992913Sobrien char *where = kd->argspc; 901573Srgrimes 91174989Sjeff if (buflen < sizeof (struct file *) + sizeof (struct file)) 92174989Sjeff return (0); 93174989Sjeff if (KREAD(kd, allproc_o, &p)) { 94174989Sjeff _kvm_err(kd, kd->program, "cannot read allproc"); 95174989Sjeff return (0); 96174989Sjeff } 97174989Sjeff for (; p != NULL; p = LIST_NEXT(&proc, p_list)) { 98174989Sjeff if (KREAD(kd, (u_long)p, &proc)) { 99174989Sjeff _kvm_err(kd, kd->program, "can't read proc at %x", p); 100174989Sjeff goto fail; 101174989Sjeff } 102174989Sjeff if (proc.p_state == PRS_NEW) 103174989Sjeff continue; 104174989Sjeff if (proc.p_fd == NULL) 105174989Sjeff continue; 106174989Sjeff if (KREAD(kd, (u_long)p->p_fd, &filed)) { 107174989Sjeff _kvm_err(kd, kd->program, "can't read filedesc at %x", 108174989Sjeff p->p_fd); 109174989Sjeff goto fail; 110174989Sjeff } 111174989Sjeff if (filed.fd_lastfile + 1 > ocnt) { 112174989Sjeff ocnt = filed.fd_lastfile + 1; 113174989Sjeff free(ofiles); 114174989Sjeff ofiles = (struct file **)_kvm_malloc(kd, 115174989Sjeff ocnt * sizeof(struct file *)); 116174989Sjeff if (ofiles == 0) 117174989Sjeff return (0); 118174989Sjeff } 119174989Sjeff if (KREADN(kd, (u_long)filed.fd_ofiles, ofiles, 120174989Sjeff ocnt * sizeof(struct file *))) { 121174989Sjeff _kvm_err(kd, kd->program, "can't read ofiles at %x", 122174989Sjeff filed.fd_ofiles); 1231573Srgrimes return (0); 1241573Srgrimes } 125174989Sjeff for (i = 0; i <= filed.fd_lastfile; i++) { 126174989Sjeff if ((fp = ofiles[i]) == NULL) 127174989Sjeff continue; 128174989Sjeff /* 129174989Sjeff * copyout filehead (legacy) 130174989Sjeff */ 131174989Sjeff if (!once) { 132174989Sjeff *(struct file **)kd->argspc = fp; 133174989Sjeff *(struct file **)where = fp; 134174989Sjeff buflen -= sizeof (fp); 135174989Sjeff where += sizeof (fp); 136174989Sjeff once = 1; 137174989Sjeff } 138174989Sjeff if (buflen < sizeof (struct file)) 139174989Sjeff goto fail; 1401573Srgrimes if (KREAD(kd, (long)fp, ((struct file *)where))) { 1411573Srgrimes _kvm_err(kd, kd->program, "can't read kfp"); 142174989Sjeff goto fail; 1431573Srgrimes } 1441573Srgrimes buflen -= sizeof (struct file); 1451573Srgrimes fp = (struct file *)where; 1461573Srgrimes where += sizeof (struct file); 1471573Srgrimes n++; 1481573Srgrimes } 1491573Srgrimes } 150174989Sjeff free(ofiles); 151174989Sjeff return (n); 152174989Sjefffail: 153174989Sjeff free(ofiles); 154174989Sjeff return (0); 155174989Sjeff 1561573Srgrimes} 1571573Srgrimes 1581573Srgrimeschar * 1591573Srgrimeskvm_getfiles(kd, op, arg, cnt) 1601573Srgrimes kvm_t *kd; 1611573Srgrimes int op, arg; 1621573Srgrimes int *cnt; 1631573Srgrimes{ 164174989Sjeff int mib[2], st, n, nfiles, nprocs; 16538534Sdfr size_t size; 1661573Srgrimes 167174989Sjeff _kvm_syserr(kd, kd->program, "kvm_getfiles has been broken for years"); 168174989Sjeff return (0); 1691573Srgrimes if (ISALIVE(kd)) { 1701573Srgrimes size = 0; 1711573Srgrimes mib[0] = CTL_KERN; 1721573Srgrimes mib[1] = KERN_FILE; 1731573Srgrimes st = sysctl(mib, 2, NULL, &size, NULL, 0); 1741573Srgrimes if (st == -1) { 17557321Speter _kvm_syserr(kd, kd->program, "kvm_getfiles"); 1761573Srgrimes return (0); 1771573Srgrimes } 1781573Srgrimes if (kd->argspc == 0) 1791573Srgrimes kd->argspc = (char *)_kvm_malloc(kd, size); 1801573Srgrimes else if (kd->arglen < size) 1811573Srgrimes kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 1821573Srgrimes if (kd->argspc == 0) 1831573Srgrimes return (0); 1841573Srgrimes kd->arglen = size; 1851573Srgrimes st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); 186174989Sjeff if (st != 0) { 1871573Srgrimes _kvm_syserr(kd, kd->program, "kvm_getfiles"); 1881573Srgrimes return (0); 1891573Srgrimes } 190174989Sjeff nfiles = size / sizeof(struct xfile); 1911573Srgrimes } else { 192174989Sjeff struct nlist nl[4], *p; 1931573Srgrimes 194174989Sjeff nl[0].n_name = "_allproc"; 195174989Sjeff nl[1].n_name = "_nprocs"; 196174989Sjeff nl[2].n_name = "_nfiles"; 197174989Sjeff nl[3].n_name = 0; 1981573Srgrimes 1991573Srgrimes if (kvm_nlist(kd, nl) != 0) { 2001573Srgrimes for (p = nl; p->n_type != 0; ++p) 2011573Srgrimes ; 2021573Srgrimes _kvm_err(kd, kd->program, 2031573Srgrimes "%s: no such symbol", p->n_name); 2041573Srgrimes return (0); 2051573Srgrimes } 206174989Sjeff if (KREAD(kd, nl[1].n_value, &nprocs)) { 207174989Sjeff _kvm_err(kd, kd->program, "can't read nprocs"); 208174989Sjeff return (0); 209174989Sjeff } 210174989Sjeff if (KREAD(kd, nl[2].n_value, &nfiles)) { 2111573Srgrimes _kvm_err(kd, kd->program, "can't read nfiles"); 2121573Srgrimes return (0); 2131573Srgrimes } 214174989Sjeff size = sizeof(void *) + (nfiles + 10) * sizeof(struct file); 2151573Srgrimes if (kd->argspc == 0) 2161573Srgrimes kd->argspc = (char *)_kvm_malloc(kd, size); 2171573Srgrimes else if (kd->arglen < size) 2181573Srgrimes kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 2191573Srgrimes if (kd->argspc == 0) 2201573Srgrimes return (0); 2211573Srgrimes kd->arglen = size; 222174989Sjeff n = kvm_deadfiles(kd, op, arg, nl[0].n_value, nprocs); 223174989Sjeff if (n != nfiles) { 224174989Sjeff _kvm_err(kd, kd->program, "inconsistant nfiles"); 2251573Srgrimes return (0); 226174989Sjeff } 227174989Sjeff nfiles = n; 2281573Srgrimes } 2291573Srgrimes *cnt = nfiles; 2301573Srgrimes return (kd->argspc); 2311573Srgrimes} 232