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>
43 #include <sys/ioctl.h>
44 #include <sys/kinfo.h>
48 #include <vm/vm_param.h>
49 #include <vm/swap_pager.h>
51 #include <sys/sysctl.h>
61 #include "kvm_private.h"
63 #define KREAD(kd, addr, obj) \
64 (kvm_read(kd, addr, obj, sizeof(*obj)) != sizeof(*obj))
66 /* XXX copied from sys/kern/subr_kcore.c */
68 kcore_make_file(struct kinfo_file
*ufile
, struct file
*kfile
,
69 pid_t pid
, uid_t owner
, int n
)
71 bzero(ufile
, sizeof(*ufile
));
72 ufile
->f_size
= sizeof(*ufile
);
77 ufile
->f_file
= kfile
;
78 ufile
->f_data
= kfile
->f_data
;
79 ufile
->f_type
= kfile
->f_type
;
80 ufile
->f_count
= kfile
->f_count
;
81 ufile
->f_msgcount
= kfile
->f_msgcount
;
82 ufile
->f_offset
= kfile
->f_offset
;
83 ufile
->f_flag
= kfile
->f_flag
;
87 * Get file structures.
90 kvm_deadfiles(kvm_t
*kd
, struct kinfo_proc
*kproc
, int kproc_cnt
, int nfiles
)
92 struct kinfo_file
*kinfo_file
= (struct kinfo_file
*)kd
->argspc
;
93 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
) {
158 size
= nfiles
* sizeof(struct kinfo_file
);
160 kd
->argspc
= _kvm_realloc(kd
, kd
->argspc
, size
);
161 if (kd
->argspc
== NULL
) {
167 kinfo_file
= (struct kinfo_file
*)kd
->argspc
;
177 kvm_getfiles(kvm_t
*kd
, int op __unused
, int arg __unused
, int *cnt
)
182 if (kvm_ishost(kd
)) {
188 st
= sysctl(mib
, 2, NULL
, &size
, NULL
, 0);
190 _kvm_syserr(kd
, kd
->program
, "sysctl KERN_FILE failed");
193 if (kd
->argspc
== NULL
)
194 kd
->argspc
= _kvm_malloc(kd
, size
);
195 else if (kd
->arglen
< (ssize_t
)size
)
196 kd
->argspc
= _kvm_realloc(kd
, kd
->argspc
, size
);
197 if (kd
->argspc
== NULL
)
200 st
= sysctl(mib
, 2, kd
->argspc
, &size
, NULL
, 0);
201 if (st
== -1 || size
% sizeof(struct kinfo_file
) != 0) {
202 _kvm_syserr(kd
, kd
->program
, "sysctl KERN_FILE failed");
205 nfiles
= size
/ sizeof(struct kinfo_file
);
207 struct kinfo_proc
*kproc0
, *kproc
;
208 int kproc_cnt
, kproc_len
;
212 * Get all processes and save them in kproc.
214 kproc0
= kvm_getprocs(kd
, KERN_PROC_ALL
, 0, &kproc_cnt
);
217 kproc_len
= kproc_cnt
* sizeof(struct kinfo_proc
);
218 kproc
= malloc(kproc_len
);
220 _kvm_syserr(kd
, kd
->program
,
221 "malloc kinfo_proc failed");
224 memcpy(kproc
, kproc0
, kproc_len
);
229 memset(nl
, 0, sizeof(nl
));
230 nl
[0].n_name
= "_nfiles";
231 if (kvm_nlist(kd
, nl
) != 0) {
232 _kvm_err(kd
, kd
->program
, "%s: no such symbol",
237 if (KREAD(kd
, nl
[0].n_value
, &nfiles
)) {
238 _kvm_err(kd
, kd
->program
, "can't read nfiles");
244 * stdio/stderr/stdout are normally duplicated
245 * across all processes.
247 nfiles
+= (kproc_cnt
* 3);
248 size
= nfiles
* sizeof(struct kinfo_file
);
249 if (kd
->argspc
== NULL
)
250 kd
->argspc
= _kvm_malloc(kd
, size
);
251 else if (kd
->arglen
< (ssize_t
)size
)
252 kd
->argspc
= _kvm_realloc(kd
, kd
->argspc
, size
);
253 if (kd
->argspc
== NULL
) {
259 nfiles
= kvm_deadfiles(kd
, kproc
, kproc_cnt
, nfiles
);
266 return (struct kinfo_file
*)(kd
->argspc
);