1*7c166415Sdsl /* $NetBSD: kvm_file.c,v 1.29 2014/02/19 20:21:22 dsl Exp $ */
2346e67f8Sthorpej
30215cc7dScgd /*-
40215cc7dScgd * Copyright (c) 1989, 1992, 1993
50215cc7dScgd * The Regents of the University of California. All rights reserved.
60215cc7dScgd *
70215cc7dScgd * Redistribution and use in source and binary forms, with or without
80215cc7dScgd * modification, are permitted provided that the following conditions
90215cc7dScgd * are met:
100215cc7dScgd * 1. Redistributions of source code must retain the above copyright
110215cc7dScgd * notice, this list of conditions and the following disclaimer.
120215cc7dScgd * 2. Redistributions in binary form must reproduce the above copyright
130215cc7dScgd * notice, this list of conditions and the following disclaimer in the
140215cc7dScgd * documentation and/or other materials provided with the distribution.
15eb7c1594Sagc * 3. Neither the name of the University nor the names of its contributors
160215cc7dScgd * may be used to endorse or promote products derived from this software
170215cc7dScgd * without specific prior written permission.
180215cc7dScgd *
190215cc7dScgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
200215cc7dScgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
210215cc7dScgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
220215cc7dScgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
230215cc7dScgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
240215cc7dScgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
250215cc7dScgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260215cc7dScgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
270215cc7dScgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
280215cc7dScgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
290215cc7dScgd * SUCH DAMAGE.
300215cc7dScgd */
310215cc7dScgd
3238e3895aSmikel #include <sys/cdefs.h>
330215cc7dScgd #if defined(LIBC_SCCS) && !defined(lint)
34346e67f8Sthorpej #if 0
350215cc7dScgd static char sccsid[] = "@(#)kvm_file.c 8.1 (Berkeley) 6/4/93";
36346e67f8Sthorpej #else
37*7c166415Sdsl __RCSID("$NetBSD: kvm_file.c,v 1.29 2014/02/19 20:21:22 dsl Exp $");
38346e67f8Sthorpej #endif
390215cc7dScgd #endif /* LIBC_SCCS and not lint */
400215cc7dScgd
410215cc7dScgd /*
420215cc7dScgd * File list interface for kvm. pstat, fstat and netstat are
430215cc7dScgd * users of this code, so we've factored it out into a separate module.
440215cc7dScgd * Thus, we keep this grunge out of the other kvm applications (i.e.,
450215cc7dScgd * most other applications are interested only in open/close/read/nlist).
460215cc7dScgd */
470215cc7dScgd
480565241bSad #define _KERNEL
490565241bSad #include <sys/types.h>
500565241bSad #undef _KERNEL
510215cc7dScgd #include <sys/param.h>
52c62a74e6Sthorpej #include <sys/lwp.h>
530215cc7dScgd #include <sys/proc.h>
540215cc7dScgd #include <sys/exec.h>
55edb9087cStron #define _KERNEL
56edb9087cStron #include <sys/file.h>
57edb9087cStron #undef _KERNEL
580215cc7dScgd #include <sys/stat.h>
590215cc7dScgd #include <sys/ioctl.h>
600215cc7dScgd #include <nlist.h>
610215cc7dScgd #include <kvm.h>
620215cc7dScgd
633b8ac18dSmrg #include <uvm/uvm_extern.h>
640215cc7dScgd
650215cc7dScgd #include <sys/sysctl.h>
660215cc7dScgd
670215cc7dScgd #include <limits.h>
680215cc7dScgd #include <ndbm.h>
690215cc7dScgd #include <paths.h>
70623230f6Sthorpej #include <string.h>
710215cc7dScgd
720215cc7dScgd #include "kvm_private.h"
730215cc7dScgd
74cda73027Sdrochner static int
756dc46b92Sjym kvm_deadfiles(kvm_t *, int, int, long, int);
76cda73027Sdrochner
770215cc7dScgd /*
780215cc7dScgd * Get file structures.
790215cc7dScgd */
80cc7ffa0dSchristos /*ARGSUSED*/
81b089e139Smikel static int
kvm_deadfiles(kvm_t * kd,int op,int arg,long ofhead,int numfiles)826dc46b92Sjym kvm_deadfiles(kvm_t *kd, int op, int arg, long ofhead, int numfiles)
830215cc7dScgd {
840213791dSchristos size_t buflen = kd->argspc_len, n = 0;
8538e3895aSmikel struct file *fp;
86cc7ffa0dSchristos struct filelist fhead;
870b7831a3Sperry char *where = kd->argspc;
880215cc7dScgd
890215cc7dScgd /*
900215cc7dScgd * first copyout filehead
910215cc7dScgd */
921794a768Scgd if (buflen < sizeof(fhead) ||
938bb0c87cSjym KREAD(kd, (u_long)ofhead, &fhead)) {
940215cc7dScgd _kvm_err(kd, kd->program, "can't read filehead");
950215cc7dScgd return (0);
960215cc7dScgd }
97cc7ffa0dSchristos buflen -= sizeof(fhead);
981794a768Scgd where += sizeof(fhead);
99cc7ffa0dSchristos (void)memcpy(kd->argspc, &fhead, sizeof(fhead));
1001794a768Scgd
1010215cc7dScgd /*
1020215cc7dScgd * followed by an array of file structures
1030215cc7dScgd */
104cc7ffa0dSchristos for (fp = fhead.lh_first; fp != 0; fp = fp->f_list.le_next) {
1050215cc7dScgd if (buflen > sizeof(struct file)) {
1068bb0c87cSjym if (KREAD(kd, (u_long)fp,
1078bb0c87cSjym ((struct file *)(void *)where))) {
1080215cc7dScgd _kvm_err(kd, kd->program, "can't read kfp");
1090215cc7dScgd return (0);
1100215cc7dScgd }
1110215cc7dScgd buflen -= sizeof(struct file);
112cc7ffa0dSchristos fp = (struct file *)(void *)where;
1131794a768Scgd where += sizeof(struct file);
1140215cc7dScgd n++;
1150215cc7dScgd }
1160215cc7dScgd }
11711e33988Slukem if (n != numfiles) {
11838e3895aSmikel _kvm_err(kd, kd->program, "inconsistent nfiles");
1190215cc7dScgd return (0);
1200215cc7dScgd }
12111e33988Slukem return (numfiles);
1220215cc7dScgd }
1230215cc7dScgd
1240215cc7dScgd char *
kvm_getfiles(kvm_t * kd,int op,int arg,int * cnt)1256dc46b92Sjym kvm_getfiles(kvm_t *kd, int op, int arg, int *cnt)
1260215cc7dScgd {
1278c814fd7Scgd size_t size;
128cc7ffa0dSchristos int mib[2], st;
129cc7ffa0dSchristos int numfiles;
1300e2293a3Smycroft struct file *fp, *fplim;
131cc7ffa0dSchristos struct filelist fhead;
1320215cc7dScgd
133a9f690aeSsimonb if (ISSYSCTL(kd)) {
1340215cc7dScgd size = 0;
1350215cc7dScgd mib[0] = CTL_KERN;
1360215cc7dScgd mib[1] = KERN_FILE;
1370215cc7dScgd st = sysctl(mib, 2, NULL, &size, NULL, 0);
1380215cc7dScgd if (st == -1) {
1390215cc7dScgd _kvm_syserr(kd, kd->program, "kvm_getprocs");
1400215cc7dScgd return (0);
1410215cc7dScgd }
1420213791dSchristos KVM_ALLOC(kd, argspc, size);
1430215cc7dScgd st = sysctl(mib, 2, kd->argspc, &size, NULL, 0);
144cc7ffa0dSchristos if (st == -1 || size < sizeof(fhead)) {
1450215cc7dScgd _kvm_syserr(kd, kd->program, "kvm_getfiles");
1460215cc7dScgd return (0);
1470215cc7dScgd }
148cc7ffa0dSchristos (void)memcpy(&fhead, kd->argspc, sizeof(fhead));
149cc7ffa0dSchristos fp = (struct file *)(void *)(kd->argspc + sizeof(fhead));
150cc7ffa0dSchristos fplim = (struct file *)(void *)(kd->argspc + size);
151cc7ffa0dSchristos for (numfiles = 0; fhead.lh_first && (fp < fplim);
152cc7ffa0dSchristos numfiles++, fp++)
153cc7ffa0dSchristos fhead.lh_first = fp->f_list.le_next;
1540215cc7dScgd } else {
1550215cc7dScgd struct nlist nl[3], *p;
1560215cc7dScgd
1571794a768Scgd nl[0].n_name = "_nfiles";
1581794a768Scgd nl[1].n_name = "_filehead";
1590215cc7dScgd nl[2].n_name = 0;
1600215cc7dScgd
1610215cc7dScgd if (kvm_nlist(kd, nl) != 0) {
1620215cc7dScgd for (p = nl; p->n_type != 0; ++p)
1630215cc7dScgd ;
1640215cc7dScgd _kvm_err(kd, kd->program,
1650215cc7dScgd "%s: no such symbol", p->n_name);
1660215cc7dScgd return (0);
1670215cc7dScgd }
168cc7ffa0dSchristos if (KREAD(kd, nl[0].n_value, &numfiles)) {
169cc7ffa0dSchristos _kvm_err(kd, kd->program, "can't read numfiles");
1700215cc7dScgd return (0);
1710215cc7dScgd }
172cc7ffa0dSchristos size = sizeof(fhead) + (numfiles + 10) * sizeof(struct file);
1730213791dSchristos KVM_ALLOC(kd, argspc, size);
174cc7ffa0dSchristos numfiles = kvm_deadfiles(kd, op, arg, (long)nl[1].n_value,
175cc7ffa0dSchristos numfiles);
176cc7ffa0dSchristos if (numfiles == 0)
1770215cc7dScgd return (0);
1780215cc7dScgd }
179cc7ffa0dSchristos *cnt = numfiles;
1800215cc7dScgd return (kd->argspc);
1810215cc7dScgd }
182