Deleted Added
full compact
procstat_files.c (181905) procstat_files.c (185548)
1/*-
2 * Copyright (c) 2007 Robert N. M. Watson
3 * All rights reserved.
4 *
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 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 2007 Robert N. M. Watson
3 * All rights reserved.
4 *
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 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/usr.bin/procstat/procstat_files.c 181905 2008-08-20 08:31:58Z ed $
26 * $FreeBSD: head/usr.bin/procstat/procstat_files.c 185548 2008-12-02 06:50:26Z peter $
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/sysctl.h>
32#include <sys/un.h>
33#include <sys/user.h>
34
35#include <netinet/in.h>
36
37#include <arpa/inet.h>
38
39#include <err.h>
40#include <inttypes.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/sysctl.h>
32#include <sys/un.h>
33#include <sys/user.h>
34
35#include <netinet/in.h>
36
37#include <arpa/inet.h>
38
39#include <err.h>
40#include <inttypes.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <libutil.h>
44
45#include "procstat.h"
46
47static const char *
48protocol_to_string(int domain, int type, int protocol)
49{
50
51 switch (domain) {
52 case AF_INET:
53 case AF_INET6:
54 switch (protocol) {
55 case IPPROTO_TCP:
56 return ("TCP");
57 case IPPROTO_UDP:
58 return ("UDP");
59 case IPPROTO_ICMP:
60 return ("ICM");
61 case IPPROTO_RAW:
62 return ("RAW");
63 case IPPROTO_SCTP:
64 return ("SCT");
65 case IPPROTO_DIVERT:
66 return ("IPD");
67 default:
68 return ("IP?");
69 }
70
71 case AF_LOCAL:
72 switch (type) {
73 case SOCK_STREAM:
74 return ("UDS");
75 case SOCK_DGRAM:
76 return ("UDD");
77 default:
78 return ("UD?");
79 }
80 default:
81 return ("?");
82 }
83}
84
85static void
86addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
87{
88 char buffer2[INET6_ADDRSTRLEN];
89 struct sockaddr_in6 *sin6;
90 struct sockaddr_in *sin;
91 struct sockaddr_un *sun;
92
93 switch (ss->ss_family) {
94 case AF_LOCAL:
95 sun = (struct sockaddr_un *)ss;
96 if (strlen(sun->sun_path) == 0)
97 strlcpy(buffer, "-", buflen);
98 else
99 strlcpy(buffer, sun->sun_path, buflen);
100 break;
101
102 case AF_INET:
103 sin = (struct sockaddr_in *)ss;
104 snprintf(buffer, buflen, "%s:%d", inet_ntoa(sin->sin_addr),
105 ntohs(sin->sin_port));
106 break;
107
108 case AF_INET6:
109 sin6 = (struct sockaddr_in6 *)ss;
110 if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2,
111 sizeof(buffer2)) != NULL)
112 snprintf(buffer, buflen, "%s.%d", buffer2,
113 ntohs(sin6->sin6_port));
114 else
115 strlcpy(buffer, "-", sizeof(buffer));
116 break;
117
118 default:
119 strlcpy(buffer, "", buflen);
120 break;
121 }
122}
123
124static void
125print_address(struct sockaddr_storage *ss)
126{
127 char addr[PATH_MAX];
128
129 addr_to_string(ss, addr, sizeof(addr));
130 printf("%s", addr);
131}
132
133void
134procstat_files(pid_t pid, struct kinfo_proc *kipp)
135{
136 struct kinfo_file *freep, *kif;
45
46#include "procstat.h"
47
48static const char *
49protocol_to_string(int domain, int type, int protocol)
50{
51
52 switch (domain) {
53 case AF_INET:
54 case AF_INET6:
55 switch (protocol) {
56 case IPPROTO_TCP:
57 return ("TCP");
58 case IPPROTO_UDP:
59 return ("UDP");
60 case IPPROTO_ICMP:
61 return ("ICM");
62 case IPPROTO_RAW:
63 return ("RAW");
64 case IPPROTO_SCTP:
65 return ("SCT");
66 case IPPROTO_DIVERT:
67 return ("IPD");
68 default:
69 return ("IP?");
70 }
71
72 case AF_LOCAL:
73 switch (type) {
74 case SOCK_STREAM:
75 return ("UDS");
76 case SOCK_DGRAM:
77 return ("UDD");
78 default:
79 return ("UD?");
80 }
81 default:
82 return ("?");
83 }
84}
85
86static void
87addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen)
88{
89 char buffer2[INET6_ADDRSTRLEN];
90 struct sockaddr_in6 *sin6;
91 struct sockaddr_in *sin;
92 struct sockaddr_un *sun;
93
94 switch (ss->ss_family) {
95 case AF_LOCAL:
96 sun = (struct sockaddr_un *)ss;
97 if (strlen(sun->sun_path) == 0)
98 strlcpy(buffer, "-", buflen);
99 else
100 strlcpy(buffer, sun->sun_path, buflen);
101 break;
102
103 case AF_INET:
104 sin = (struct sockaddr_in *)ss;
105 snprintf(buffer, buflen, "%s:%d", inet_ntoa(sin->sin_addr),
106 ntohs(sin->sin_port));
107 break;
108
109 case AF_INET6:
110 sin6 = (struct sockaddr_in6 *)ss;
111 if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2,
112 sizeof(buffer2)) != NULL)
113 snprintf(buffer, buflen, "%s.%d", buffer2,
114 ntohs(sin6->sin6_port));
115 else
116 strlcpy(buffer, "-", sizeof(buffer));
117 break;
118
119 default:
120 strlcpy(buffer, "", buflen);
121 break;
122 }
123}
124
125static void
126print_address(struct sockaddr_storage *ss)
127{
128 char addr[PATH_MAX];
129
130 addr_to_string(ss, addr, sizeof(addr));
131 printf("%s", addr);
132}
133
134void
135procstat_files(pid_t pid, struct kinfo_proc *kipp)
136{
137 struct kinfo_file *freep, *kif;
137 int error, name[4];
138 unsigned int i;
138 int i, cnt;
139 const char *str;
139 const char *str;
140 size_t len;
141
142 if (!hflag)
143 printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n",
144 "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET",
145 "PRO", "NAME");
146
140
141 if (!hflag)
142 printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n",
143 "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET",
144 "PRO", "NAME");
145
147 name[0] = CTL_KERN;
148 name[1] = KERN_PROC;
149 name[2] = KERN_PROC_FILEDESC;
150 name[3] = pid;
151
152 error = sysctl(name, 4, NULL, &len, NULL, 0);
153 if (error < 0 && errno != ESRCH && errno != EPERM) {
154 warn("sysctl: kern.proc.filedesc: %d", pid);
155 return;
156 }
157 if (error < 0)
158 return;
159
160 freep = kif = malloc(len);
161 if (kif == NULL)
162 err(-1, "malloc");
163
164 if (sysctl(name, 4, kif, &len, NULL, 0) < 0) {
165 warn("sysctl: kern.proc.filedesc %d", pid);
166 free(freep);
167 return;
168 }
169
170 for (i = 0; i < len / sizeof(*kif); i++, kif++) {
171 if (kif->kf_structsize != sizeof(*kif))
172 errx(-1, "kinfo_file mismatch");
146 freep = kinfo_getfile(pid, &cnt);
147 for (i = 0; i < cnt; i++) {
148 kif = &freep[i];
149
173 printf("%5d ", pid);
174 printf("%-16s ", kipp->ki_comm);
175 switch (kif->kf_fd) {
176 case KF_FD_TYPE_CWD:
177 printf(" cwd ");
178 break;
179
180 case KF_FD_TYPE_ROOT:
181 printf("root ");
182 break;
183
184 case KF_FD_TYPE_JAIL:
185 printf("jail ");
186 break;
187
188 default:
189 printf("%4d ", kif->kf_fd);
190 break;
191 }
192 switch (kif->kf_type) {
193 case KF_TYPE_VNODE:
194 str = "v";
195 break;
196
197 case KF_TYPE_SOCKET:
198 str = "s";
199 break;
200
201 case KF_TYPE_PIPE:
202 str = "p";
203 break;
204
205 case KF_TYPE_FIFO:
206 str = "f";
207 break;
208
209 case KF_TYPE_KQUEUE:
210 str = "k";
211 break;
212
213 case KF_TYPE_CRYPTO:
214 str = "c";
215 break;
216
217 case KF_TYPE_MQUEUE:
218 str = "m";
219 break;
220
221 case KF_TYPE_SHM:
222 str = "h";
223 break;
224
225 case KF_TYPE_PTS:
226 str = "t";
227 break;
228
229 case KF_TYPE_SEM:
230 str = "e";
231 break;
232
233 case KF_TYPE_NONE:
234 case KF_TYPE_UNKNOWN:
235 default:
236 str = "?";
237 break;
238 }
239 printf("%1s ", str);
240 str = "-";
241 if (kif->kf_type == KF_TYPE_VNODE) {
242 switch (kif->kf_vnode_type) {
243 case KF_VTYPE_VREG:
244 str = "r";
245 break;
246
247 case KF_VTYPE_VDIR:
248 str = "d";
249 break;
250
251 case KF_VTYPE_VBLK:
252 str = "b";
253 break;
254
255 case KF_VTYPE_VCHR:
256 str = "c";
257 break;
258
259 case KF_VTYPE_VLNK:
260 str = "l";
261 break;
262
263 case KF_VTYPE_VSOCK:
264 str = "s";
265 break;
266
267 case KF_VTYPE_VFIFO:
268 str = "f";
269 break;
270
271 case KF_VTYPE_VBAD:
272 str = "x";
273 break;
274
275 case KF_VTYPE_VNON:
276 case KF_VTYPE_UNKNOWN:
277 default:
278 str = "?";
279 break;
280 }
281 }
282 printf("%1s ", str);
283 printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-");
284 printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-");
285 printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-");
286 printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-");
287 printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-");
288 printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-");
289 printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-");
290 printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-");
291 if (kif->kf_ref_count > -1)
292 printf("%3d ", kif->kf_ref_count);
293 else
294 printf("%3c ", '-');
295 if (kif->kf_offset > -1)
296 printf("%7jd ", (intmax_t)kif->kf_offset);
297 else
298 printf("%7c ", '-');
299
300 switch (kif->kf_type) {
301 case KF_TYPE_VNODE:
302 case KF_TYPE_FIFO:
303 case KF_TYPE_PTS:
304 printf("%-3s ", "-");
305 printf("%-18s", kif->kf_path);
306 break;
307
308 case KF_TYPE_SOCKET:
309 printf("%-3s ",
310 protocol_to_string(kif->kf_sock_domain,
311 kif->kf_sock_type, kif->kf_sock_protocol));
312 /*
313 * While generally we like to print two addresses,
314 * local and peer, for sockets, it turns out to be
315 * more useful to print the first non-nul address for
316 * local sockets, as typically they aren't bound and
317 * connected, and the path strings can get long.
318 */
319 if (kif->kf_sock_domain == AF_LOCAL) {
320 struct sockaddr_un *sun =
321 (struct sockaddr_un *)&kif->kf_sa_local;
322
323 if (sun->sun_path[0] != 0)
324 print_address(&kif->kf_sa_local);
325 else
326 print_address(&kif->kf_sa_peer);
327 } else {
328 print_address(&kif->kf_sa_local);
329 printf(" ");
330 print_address(&kif->kf_sa_peer);
331 }
332 break;
333
334 default:
335 printf("%-3s ", "-");
336 printf("%-18s", "-");
337 }
338
339 printf("\n");
340 }
341 free(freep);
342}
150 printf("%5d ", pid);
151 printf("%-16s ", kipp->ki_comm);
152 switch (kif->kf_fd) {
153 case KF_FD_TYPE_CWD:
154 printf(" cwd ");
155 break;
156
157 case KF_FD_TYPE_ROOT:
158 printf("root ");
159 break;
160
161 case KF_FD_TYPE_JAIL:
162 printf("jail ");
163 break;
164
165 default:
166 printf("%4d ", kif->kf_fd);
167 break;
168 }
169 switch (kif->kf_type) {
170 case KF_TYPE_VNODE:
171 str = "v";
172 break;
173
174 case KF_TYPE_SOCKET:
175 str = "s";
176 break;
177
178 case KF_TYPE_PIPE:
179 str = "p";
180 break;
181
182 case KF_TYPE_FIFO:
183 str = "f";
184 break;
185
186 case KF_TYPE_KQUEUE:
187 str = "k";
188 break;
189
190 case KF_TYPE_CRYPTO:
191 str = "c";
192 break;
193
194 case KF_TYPE_MQUEUE:
195 str = "m";
196 break;
197
198 case KF_TYPE_SHM:
199 str = "h";
200 break;
201
202 case KF_TYPE_PTS:
203 str = "t";
204 break;
205
206 case KF_TYPE_SEM:
207 str = "e";
208 break;
209
210 case KF_TYPE_NONE:
211 case KF_TYPE_UNKNOWN:
212 default:
213 str = "?";
214 break;
215 }
216 printf("%1s ", str);
217 str = "-";
218 if (kif->kf_type == KF_TYPE_VNODE) {
219 switch (kif->kf_vnode_type) {
220 case KF_VTYPE_VREG:
221 str = "r";
222 break;
223
224 case KF_VTYPE_VDIR:
225 str = "d";
226 break;
227
228 case KF_VTYPE_VBLK:
229 str = "b";
230 break;
231
232 case KF_VTYPE_VCHR:
233 str = "c";
234 break;
235
236 case KF_VTYPE_VLNK:
237 str = "l";
238 break;
239
240 case KF_VTYPE_VSOCK:
241 str = "s";
242 break;
243
244 case KF_VTYPE_VFIFO:
245 str = "f";
246 break;
247
248 case KF_VTYPE_VBAD:
249 str = "x";
250 break;
251
252 case KF_VTYPE_VNON:
253 case KF_VTYPE_UNKNOWN:
254 default:
255 str = "?";
256 break;
257 }
258 }
259 printf("%1s ", str);
260 printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-");
261 printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-");
262 printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-");
263 printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-");
264 printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-");
265 printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-");
266 printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-");
267 printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-");
268 if (kif->kf_ref_count > -1)
269 printf("%3d ", kif->kf_ref_count);
270 else
271 printf("%3c ", '-');
272 if (kif->kf_offset > -1)
273 printf("%7jd ", (intmax_t)kif->kf_offset);
274 else
275 printf("%7c ", '-');
276
277 switch (kif->kf_type) {
278 case KF_TYPE_VNODE:
279 case KF_TYPE_FIFO:
280 case KF_TYPE_PTS:
281 printf("%-3s ", "-");
282 printf("%-18s", kif->kf_path);
283 break;
284
285 case KF_TYPE_SOCKET:
286 printf("%-3s ",
287 protocol_to_string(kif->kf_sock_domain,
288 kif->kf_sock_type, kif->kf_sock_protocol));
289 /*
290 * While generally we like to print two addresses,
291 * local and peer, for sockets, it turns out to be
292 * more useful to print the first non-nul address for
293 * local sockets, as typically they aren't bound and
294 * connected, and the path strings can get long.
295 */
296 if (kif->kf_sock_domain == AF_LOCAL) {
297 struct sockaddr_un *sun =
298 (struct sockaddr_un *)&kif->kf_sa_local;
299
300 if (sun->sun_path[0] != 0)
301 print_address(&kif->kf_sa_local);
302 else
303 print_address(&kif->kf_sa_peer);
304 } else {
305 print_address(&kif->kf_sa_local);
306 printf(" ");
307 print_address(&kif->kf_sa_peer);
308 }
309 break;
310
311 default:
312 printf("%-3s ", "-");
313 printf("%-18s", "-");
314 }
315
316 printf("\n");
317 }
318 free(freep);
319}