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