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
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
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>
44 #include <sys/ioctl.h>
45 #include <sys/kinfo.h>
50 #include <vm/vm_param.h>
51 #include <vm/swap_pager.h>
53 #include <sys/sysctl.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 */
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
);
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.
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;
98 fd_files
= malloc(fd_nfiles
* sizeof(struct fdnode
));
99 if (fd_files
== NULL
) {
100 _kvm_err(kd
, kd
->program
, "alloc fd_files failed");
104 for (i
= 0; i
< kproc_cnt
; ++i
) {
105 const struct kinfo_proc
*kp
= &kproc
[i
];
111 if (KREAD(kd
, kp
->kp_fd
, &fdp
)) {
112 _kvm_err(kd
, kd
->program
, "can't read fdp");
116 if (fdp
.fd_files
== NULL
)
119 if (fdp
.fd_nfiles
> fd_nfiles
) {
120 struct fdnode
*new_fd_files
;
122 fd_nfiles
= fdp
.fd_nfiles
;
124 malloc(fd_nfiles
* sizeof(struct fdnode
));
126 if (new_fd_files
== NULL
) {
127 _kvm_err(kd
, kd
->program
,
128 "realloc fd_files failed");
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");
140 for (f
= 0; f
< fdp
.fd_nfiles
; ++f
) {
143 if (fd_files
[f
].fp
== NULL
)
145 if (KREAD(kd
, (uintptr_t)fd_files
[f
].fp
, &kf
)) {
146 _kvm_err(kd
, kd
->program
, "can't read file");
151 kcore_make_file(kinfo_file
, &kf
,
152 kp
->kp_pid
, kp
->kp_uid
, f
);
156 if (found
== nfiles
) {
160 size
= nfiles
* sizeof(struct kinfo_file
);
162 kd
->argspc
= _kvm_realloc(kd
, kd
->argspc
, size
);
163 if (kd
->argspc
== NULL
) {
169 kinfo_file
= (struct kinfo_file
*)kd
->argspc
;
179 kvm_getfiles(kvm_t
*kd
, int op
, int arg
, int *cnt
)
184 if (kvm_ishost(kd
)) {
190 st
= sysctl(mib
, 2, NULL
, &size
, NULL
, 0);
192 _kvm_syserr(kd
, kd
->program
, "sysctl KERN_FILE failed");
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
)
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");
207 nfiles
= size
/ sizeof(struct kinfo_file
);
209 struct kinfo_proc
*kproc0
, *kproc
;
210 int kproc_cnt
, kproc_len
;
214 * Get all processes and save them in kproc.
216 kproc0
= kvm_getprocs(kd
, KERN_PROC_ALL
, 0, &kproc_cnt
);
219 kproc_len
= kproc_cnt
* sizeof(struct kinfo_proc
);
220 kproc
= malloc(kproc_len
);
222 _kvm_syserr(kd
, kd
->program
,
223 "malloc kinfo_proc failed");
226 memcpy(kproc
, kproc0
, kproc_len
);
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",
239 if (KREAD(kd
, nl
[0].n_value
, &nfiles
)) {
240 _kvm_err(kd
, kd
->program
, "can't read nfiles");
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
) {
261 nfiles
= kvm_deadfiles(kd
, kproc
, kproc_cnt
, nfiles
);
268 return (struct kinfo_file
*)(kd
->argspc
);