mfiutil(8): Use MAN instead of MAN8.
[dragonfly.git] / lib / libkvm / kvm_file.c
blobce859e05649f14b6472a8ed10e497f7dd4ee44fc
1 /*-
2 * Copyright (c) 1989, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
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 * 3. 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.
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.
29 * @(#)kvm_file.c 8.1 (Berkeley) 6/4/93
30 * $FreeBSD: src/lib/libkvm/kvm_file.c,v 1.11 2000/02/18 16:39:00 peter Exp $
34 * File list interface for kvm.
37 #include <sys/user.h> /* MUST BE FIRST */
38 #include <sys/param.h>
39 #include <sys/proc.h>
40 #define _KERNEL
41 #include <sys/file.h>
42 #undef _KERNEL
43 #include <sys/stat.h>
44 #include <sys/ioctl.h>
45 #include <sys/kinfo.h>
46 #include <nlist.h>
47 #include <kvm.h>
49 #include <vm/vm.h>
50 #include <vm/vm_param.h>
51 #include <vm/swap_pager.h>
53 #include <sys/sysctl.h>
55 #include <limits.h>
56 #include <ndbm.h>
57 #include <paths.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
62 #include "kvm_private.h"
64 #define KREAD(kd, addr, obj) \
65 (kvm_read(kd, addr, obj, sizeof(*obj)) != sizeof(*obj))
67 /* XXX copied from sys/kern/subr_kcore.c */
68 static void
69 kcore_make_file(struct kinfo_file *ufile, struct file *kfile,
70 pid_t pid, uid_t owner, int n)
72 bzero(ufile, sizeof(*ufile));
73 ufile->f_size = sizeof(*ufile);
74 ufile->f_pid = pid;
75 ufile->f_uid = owner;
77 ufile->f_fd = n;
78 ufile->f_file = kfile;
79 ufile->f_data = kfile->f_data;
80 ufile->f_type = kfile->f_type;
81 ufile->f_count = kfile->f_count;
82 ufile->f_msgcount = kfile->f_msgcount;
83 ufile->f_offset = kfile->f_offset;
84 ufile->f_flag = kfile->f_flag;
88 * Get file structures.
90 static int
91 kvm_deadfiles(kvm_t *kd, struct kinfo_proc *kproc, int kproc_cnt, int nfiles)
93 struct kinfo_file *kinfo_file = (struct kinfo_file *)kd->argspc;
94 struct fdnode *fd_files;
95 int i, fd_nfiles, found = 0;
97 fd_nfiles = NDFILE;
98 fd_files = malloc(fd_nfiles * sizeof(struct fdnode));
99 if (fd_files == NULL) {
100 _kvm_err(kd, kd->program, "alloc fd_files failed");
101 return 0;
104 for (i = 0; i < kproc_cnt; ++i) {
105 const struct kinfo_proc *kp = &kproc[i];
106 struct filedesc fdp;
107 int n, f;
109 if (kp->kp_fd == 0)
110 continue;
111 if (KREAD(kd, kp->kp_fd, &fdp)) {
112 _kvm_err(kd, kd->program, "can't read fdp");
113 free(fd_files);
114 return 0;
116 if (fdp.fd_files == NULL)
117 continue;
119 if (fdp.fd_nfiles > fd_nfiles) {
120 struct fdnode *new_fd_files;
122 fd_nfiles = fdp.fd_nfiles;
123 new_fd_files =
124 malloc(fd_nfiles * sizeof(struct fdnode));
125 free(fd_files);
126 if (new_fd_files == NULL) {
127 _kvm_err(kd, kd->program,
128 "realloc fd_files failed");
129 return 0;
131 fd_files = new_fd_files;
133 n = fdp.fd_nfiles * sizeof(struct fdnode);
135 if (kvm_read(kd, (uintptr_t)fdp.fd_files, fd_files, n) != n) {
136 _kvm_err(kd, kd->program, "can't read fd_files");
137 free(fd_files);
138 return 0;
140 for (f = 0; f < fdp.fd_nfiles; ++f) {
141 struct file kf;
143 if (fd_files[f].fp == NULL)
144 continue;
145 if (KREAD(kd, (uintptr_t)fd_files[f].fp, &kf)) {
146 _kvm_err(kd, kd->program, "can't read file");
147 free(fd_files);
148 return 0;
151 kcore_make_file(kinfo_file, &kf,
152 kp->kp_pid, kp->kp_uid, f);
153 kinfo_file++;
154 found++;
156 if (found == nfiles) {
157 size_t size;
159 nfiles *= 2;
160 size = nfiles * sizeof(struct kinfo_file);
162 kd->argspc = _kvm_realloc(kd, kd->argspc, size);
163 if (kd->argspc == NULL) {
164 free(fd_files);
165 return 0;
167 kd->arglen = size;
169 kinfo_file = (struct kinfo_file *)kd->argspc;
170 kinfo_file += found;
174 free(fd_files);
175 return found;
178 struct kinfo_file *
179 kvm_getfiles(kvm_t *kd, int op, int arg, int *cnt)
181 int nfiles;
182 size_t size;
184 if (kvm_ishost(kd)) {
185 int mib[2], st;
187 size = 0;
188 mib[0] = CTL_KERN;
189 mib[1] = KERN_FILE;
190 st = sysctl(mib, 2, NULL, &size, NULL, 0);
191 if (st == -1) {
192 _kvm_syserr(kd, kd->program, "sysctl KERN_FILE failed");
193 return NULL;
195 if (kd->argspc == NULL)
196 kd->argspc = _kvm_malloc(kd, size);
197 else if (kd->arglen < size)
198 kd->argspc = _kvm_realloc(kd, kd->argspc, size);
199 if (kd->argspc == NULL)
200 return NULL;
201 kd->arglen = size;
202 st = sysctl(mib, 2, kd->argspc, &size, NULL, 0);
203 if (st == -1 || size % sizeof(struct kinfo_file) != 0) {
204 _kvm_syserr(kd, kd->program, "sysctl KERN_FILE failed");
205 return NULL;
207 nfiles = size / sizeof(struct kinfo_file);
208 } else {
209 struct kinfo_proc *kproc0, *kproc;
210 int kproc_cnt, kproc_len;
211 struct nlist nl[2];
214 * Get all processes and save them in kproc.
216 kproc0 = kvm_getprocs(kd, KERN_PROC_ALL, 0, &kproc_cnt);
217 if (kproc0 == NULL)
218 return NULL;
219 kproc_len = kproc_cnt * sizeof(struct kinfo_proc);
220 kproc = malloc(kproc_len);
221 if (kproc == NULL) {
222 _kvm_syserr(kd, kd->program,
223 "malloc kinfo_proc failed");
224 return NULL;
226 memcpy(kproc, kproc0, kproc_len);
229 * Get the # of files
231 memset(nl, 0, sizeof(nl));
232 nl[0].n_name = "_nfiles";
233 if (kvm_nlist(kd, nl) != 0) {
234 _kvm_err(kd, kd->program, "%s: no such symbol",
235 nl[0].n_name);
236 free(kproc);
237 return NULL;
239 if (KREAD(kd, nl[0].n_value, &nfiles)) {
240 _kvm_err(kd, kd->program, "can't read nfiles");
241 free(kproc);
242 return NULL;
246 * stdio/stderr/stdout are normally duplicated
247 * across all processes.
249 nfiles += (kproc_cnt * 3);
250 size = nfiles * sizeof(struct kinfo_file);
251 if (kd->argspc == NULL)
252 kd->argspc = _kvm_malloc(kd, size);
253 else if (kd->arglen < size)
254 kd->argspc = _kvm_realloc(kd, kd->argspc, size);
255 if (kd->argspc == NULL) {
256 free(kproc);
257 return NULL;
259 kd->arglen = size;
261 nfiles = kvm_deadfiles(kd, kproc, kproc_cnt, nfiles);
262 free(kproc);
264 if (nfiles == 0)
265 return NULL;
267 *cnt = nfiles;
268 return (struct kinfo_file *)(kd->argspc);