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: releng/10.2/lib/libkvm/kvm_file.c 217744 2011-01-23 11:08:28Z uqs $"); 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) \ 72217744Suqs (kvm_read(kd, addr, obj, (cnt)) != (ssize_t)(cnt)) 73174989Sjeff 741573Srgrimes/* 751573Srgrimes * Get file structures. 761573Srgrimes */ 7717141Sjkhstatic int 78217744Suqskvm_deadfiles(kvm_t *kd, int op __unused, int arg __unused, long allproc_o, 79217744Suqs int nprocs __unused) 801573Srgrimes{ 81174989Sjeff struct proc proc; 82174989Sjeff struct filedesc filed; 83174989Sjeff int buflen = kd->arglen, ocnt = 0, n = 0, once = 0, i; 84174989Sjeff struct file **ofiles; 8514523Shsu struct file *fp; 86174989Sjeff struct proc *p; 8792913Sobrien char *where = kd->argspc; 881573Srgrimes 89217744Suqs if (buflen < (int)(sizeof(struct file *) + sizeof(struct file))) 90174989Sjeff return (0); 91174989Sjeff if (KREAD(kd, allproc_o, &p)) { 92174989Sjeff _kvm_err(kd, kd->program, "cannot read allproc"); 93174989Sjeff return (0); 94174989Sjeff } 95174989Sjeff for (; p != NULL; p = LIST_NEXT(&proc, p_list)) { 96174989Sjeff if (KREAD(kd, (u_long)p, &proc)) { 97217744Suqs _kvm_err(kd, kd->program, "can't read proc at %p", p); 98174989Sjeff goto fail; 99174989Sjeff } 100174989Sjeff if (proc.p_state == PRS_NEW) 101174989Sjeff continue; 102174989Sjeff if (proc.p_fd == NULL) 103174989Sjeff continue; 104174989Sjeff if (KREAD(kd, (u_long)p->p_fd, &filed)) { 105217744Suqs _kvm_err(kd, kd->program, "can't read filedesc at %p", 106174989Sjeff p->p_fd); 107174989Sjeff goto fail; 108174989Sjeff } 109174989Sjeff if (filed.fd_lastfile + 1 > ocnt) { 110174989Sjeff ocnt = filed.fd_lastfile + 1; 111174989Sjeff free(ofiles); 112174989Sjeff ofiles = (struct file **)_kvm_malloc(kd, 113174989Sjeff ocnt * sizeof(struct file *)); 114174989Sjeff if (ofiles == 0) 115174989Sjeff return (0); 116174989Sjeff } 117174989Sjeff if (KREADN(kd, (u_long)filed.fd_ofiles, ofiles, 118174989Sjeff ocnt * sizeof(struct file *))) { 119217744Suqs _kvm_err(kd, kd->program, "can't read ofiles at %p", 120174989Sjeff filed.fd_ofiles); 1211573Srgrimes return (0); 1221573Srgrimes } 123174989Sjeff for (i = 0; i <= filed.fd_lastfile; i++) { 124174989Sjeff if ((fp = ofiles[i]) == NULL) 125174989Sjeff continue; 126174989Sjeff /* 127174989Sjeff * copyout filehead (legacy) 128174989Sjeff */ 129174989Sjeff if (!once) { 130174989Sjeff *(struct file **)kd->argspc = fp; 131174989Sjeff *(struct file **)where = fp; 132174989Sjeff buflen -= sizeof (fp); 133174989Sjeff where += sizeof (fp); 134174989Sjeff once = 1; 135174989Sjeff } 136217744Suqs if (buflen < (int)sizeof(struct file)) 137174989Sjeff goto fail; 1381573Srgrimes if (KREAD(kd, (long)fp, ((struct file *)where))) { 1391573Srgrimes _kvm_err(kd, kd->program, "can't read kfp"); 140174989Sjeff goto fail; 1411573Srgrimes } 1421573Srgrimes buflen -= sizeof (struct file); 1431573Srgrimes fp = (struct file *)where; 1441573Srgrimes where += sizeof (struct file); 1451573Srgrimes n++; 1461573Srgrimes } 1471573Srgrimes } 148174989Sjeff free(ofiles); 149174989Sjeff return (n); 150174989Sjefffail: 151174989Sjeff free(ofiles); 152174989Sjeff return (0); 153174989Sjeff 1541573Srgrimes} 1551573Srgrimes 1561573Srgrimeschar * 157217744Suqskvm_getfiles(kvm_t *kd, int op, int arg, int *cnt) 1581573Srgrimes{ 159174989Sjeff int mib[2], st, n, nfiles, nprocs; 16038534Sdfr size_t size; 1611573Srgrimes 162174989Sjeff _kvm_syserr(kd, kd->program, "kvm_getfiles has been broken for years"); 163174989Sjeff return (0); 1641573Srgrimes if (ISALIVE(kd)) { 1651573Srgrimes size = 0; 1661573Srgrimes mib[0] = CTL_KERN; 1671573Srgrimes mib[1] = KERN_FILE; 1681573Srgrimes st = sysctl(mib, 2, NULL, &size, NULL, 0); 1691573Srgrimes if (st == -1) { 17057321Speter _kvm_syserr(kd, kd->program, "kvm_getfiles"); 1711573Srgrimes return (0); 1721573Srgrimes } 1731573Srgrimes if (kd->argspc == 0) 1741573Srgrimes kd->argspc = (char *)_kvm_malloc(kd, size); 175217744Suqs else if (kd->arglen < (int)size) 1761573Srgrimes kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 1771573Srgrimes if (kd->argspc == 0) 1781573Srgrimes return (0); 1791573Srgrimes kd->arglen = size; 1801573Srgrimes st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); 181174989Sjeff if (st != 0) { 1821573Srgrimes _kvm_syserr(kd, kd->program, "kvm_getfiles"); 1831573Srgrimes return (0); 1841573Srgrimes } 185174989Sjeff nfiles = size / sizeof(struct xfile); 1861573Srgrimes } else { 187174989Sjeff struct nlist nl[4], *p; 1881573Srgrimes 189174989Sjeff nl[0].n_name = "_allproc"; 190174989Sjeff nl[1].n_name = "_nprocs"; 191174989Sjeff nl[2].n_name = "_nfiles"; 192174989Sjeff nl[3].n_name = 0; 1931573Srgrimes 1941573Srgrimes if (kvm_nlist(kd, nl) != 0) { 1951573Srgrimes for (p = nl; p->n_type != 0; ++p) 1961573Srgrimes ; 1971573Srgrimes _kvm_err(kd, kd->program, 1981573Srgrimes "%s: no such symbol", p->n_name); 1991573Srgrimes return (0); 2001573Srgrimes } 201174989Sjeff if (KREAD(kd, nl[1].n_value, &nprocs)) { 202174989Sjeff _kvm_err(kd, kd->program, "can't read nprocs"); 203174989Sjeff return (0); 204174989Sjeff } 205174989Sjeff if (KREAD(kd, nl[2].n_value, &nfiles)) { 2061573Srgrimes _kvm_err(kd, kd->program, "can't read nfiles"); 2071573Srgrimes return (0); 2081573Srgrimes } 209174989Sjeff size = sizeof(void *) + (nfiles + 10) * sizeof(struct file); 2101573Srgrimes if (kd->argspc == 0) 2111573Srgrimes kd->argspc = (char *)_kvm_malloc(kd, size); 212217744Suqs else if (kd->arglen < (int)size) 2131573Srgrimes kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 2141573Srgrimes if (kd->argspc == 0) 2151573Srgrimes return (0); 2161573Srgrimes kd->arglen = size; 217174989Sjeff n = kvm_deadfiles(kd, op, arg, nl[0].n_value, nprocs); 218174989Sjeff if (n != nfiles) { 219174989Sjeff _kvm_err(kd, kd->program, "inconsistant nfiles"); 2201573Srgrimes return (0); 221174989Sjeff } 222174989Sjeff nfiles = n; 2231573Srgrimes } 2241573Srgrimes *cnt = nfiles; 2251573Srgrimes return (kd->argspc); 2261573Srgrimes} 227