xref: /minix/minix/usr.bin/trace/service/vfs.c (revision fb9c64b2)
1 
2 #include "inc.h"
3 
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <dirent.h>
7 #include <sys/mount.h>
8 #include <sys/resource.h>
9 #include <sys/socket.h>
10 #include <sys/un.h>
11 #include <netinet/in.h>
12 #if 0 /* not yet, header is missing */
13 #include <netbt/bluetooth.h>
14 #endif
15 #include <arpa/inet.h>
16 
17 /*
18  * This function should always be used when printing a file descriptor.  It
19  * currently offers no benefit, but will in the future allow for features such
20  * as color highlighting and tracking of specific open files (TODO).
21  */
22 void
23 put_fd(struct trace_proc * proc, const char * name, int fd)
24 {
25 
26 	put_value(proc, name, "%d", fd);
27 }
28 
29 static int
30 vfs_read_out(struct trace_proc * proc, const message * m_out)
31 {
32 
33 	put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
34 
35 	return CT_NOTDONE;
36 }
37 
38 static void
39 vfs_read_in(struct trace_proc * proc, const message * m_out,
40 	const message * m_in, int failed)
41 {
42 
43 	put_buf(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf,
44 	    m_in->m_type);
45 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
46 	put_equals(proc);
47 	put_result(proc);
48 }
49 
50 static int
51 vfs_write_out(struct trace_proc * proc, const message * m_out)
52 {
53 
54 	put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
55 	put_buf(proc, "buf", 0, m_out->m_lc_vfs_readwrite.buf,
56 	    m_out->m_lc_vfs_readwrite.len);
57 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
58 
59 	return CT_DONE;
60 }
61 
62 static void
63 put_lseek_whence(struct trace_proc * proc, const char * name, int whence)
64 {
65 	const char *text = NULL;
66 
67 	if (!valuesonly) {
68 		switch (whence) {
69 		TEXT(SEEK_SET);
70 		TEXT(SEEK_CUR);
71 		TEXT(SEEK_END);
72 		}
73 	}
74 
75 	if (text != NULL)
76 		put_field(proc, name, text);
77 	else
78 		put_value(proc, name, "%d", whence);
79 }
80 
81 static int
82 vfs_lseek_out(struct trace_proc * proc, const message * m_out)
83 {
84 
85 	put_fd(proc, "fd", m_out->m_lc_vfs_lseek.fd);
86 	put_value(proc, "offset", "%"PRId64, m_out->m_lc_vfs_lseek.offset);
87 	put_lseek_whence(proc, "whence", m_out->m_lc_vfs_lseek.whence);
88 
89 	return CT_DONE;
90 }
91 
92 static void
93 vfs_lseek_in(struct trace_proc * proc, const message * __unused m_out,
94 	const message * m_in, int failed)
95 {
96 
97 	if (!failed)
98 		put_value(proc, NULL, "%"PRId64, m_in->m_vfs_lc_lseek.offset);
99 	else
100 		put_result(proc);
101 }
102 
103 static const struct flags open_flags[] = {
104 	FLAG_MASK(O_ACCMODE, O_RDONLY),
105 	FLAG_MASK(O_ACCMODE, O_WRONLY),
106 	FLAG_MASK(O_ACCMODE, O_RDWR),
107 #define ACCMODE_ENTRIES 3	/* the first N entries are for O_ACCMODE */
108 	FLAG(O_NONBLOCK),
109 	FLAG(O_APPEND),
110 	FLAG(O_SHLOCK),
111 	FLAG(O_EXLOCK),
112 	FLAG(O_ASYNC),
113 	FLAG(O_SYNC),
114 	FLAG(O_NOFOLLOW),
115 	FLAG(O_CREAT),
116 	FLAG(O_TRUNC),
117 	FLAG(O_EXCL),
118 	FLAG(O_NOCTTY),
119 	FLAG(O_DSYNC),
120 	FLAG(O_RSYNC),
121 	FLAG(O_ALT_IO),
122 	FLAG(O_DIRECT),
123 	FLAG(O_DIRECTORY),
124 	FLAG(O_CLOEXEC),
125 	FLAG(O_SEARCH),
126 	FLAG(O_NOSIGPIPE),
127 };
128 
129 static void
130 put_open_flags(struct trace_proc * proc, const char * name, int value,
131 	int full)
132 {
133 	const struct flags *fp;
134 	unsigned int num;
135 
136 	fp = open_flags;
137 	num = COUNT(open_flags);
138 
139 	/*
140 	 * If we're not printing a full open()-style set of flags, but instead
141 	 * just a loose set of flags, then skip the access mode altogether,
142 	 * otherwise we'd be printing O_RDONLY when no access mode is given.
143 	 */
144 	if (!full) {
145 		fp += ACCMODE_ENTRIES;
146 		num -= ACCMODE_ENTRIES;
147 	}
148 
149 	put_flags(proc, name, fp, num, "0x%x", value);
150 }
151 
152 static const struct flags mode_flags[] = {
153 	FLAG_MASK(S_IFMT, S_IFIFO),
154 	FLAG_MASK(S_IFMT, S_IFCHR),
155 	FLAG_MASK(S_IFMT, S_IFDIR),
156 	FLAG_MASK(S_IFMT, S_IFBLK),
157 	FLAG_MASK(S_IFMT, S_IFREG),
158 	FLAG_MASK(S_IFMT, S_IFLNK),
159 	FLAG_MASK(S_IFMT, S_IFSOCK),
160 	FLAG_MASK(S_IFMT, S_IFWHT),
161 	FLAG(S_ARCH1),
162 	FLAG(S_ARCH2),
163 	FLAG(S_ISUID),
164 	FLAG(S_ISGID),
165 	FLAG(S_ISTXT),
166 };
167 
168 /* Do not use %04o instead of 0%03o; it is octal even if greater than 0777. */
169 #define put_mode(p, n, v) \
170 	put_flags(p, n, mode_flags, COUNT(mode_flags), "0%03o", v)
171 
172 static void
173 put_path(struct trace_proc * proc, const message * m_out)
174 {
175 	size_t len;
176 
177 	if ((len = m_out->m_lc_vfs_path.len) <= M_PATH_STRING_MAX)
178 		put_buf(proc, "path", PF_LOCADDR | PF_PATH,
179 		    (vir_bytes)m_out->m_lc_vfs_path.buf, len);
180 	else
181 		put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_path.name, len);
182 }
183 
184 static int
185 vfs_open_out(struct trace_proc * proc, const message * m_out)
186 {
187 
188 	put_path(proc, m_out);
189 	put_open_flags(proc, "flags", m_out->m_lc_vfs_path.flags,
190 	    TRUE /*full*/);
191 
192 	return CT_DONE;
193 }
194 
195 /* This function is shared between creat and open. */
196 static void
197 vfs_open_in(struct trace_proc * proc, const message * __unused m_out,
198 	const message * m_in, int failed)
199 {
200 
201 	if (!failed)
202 		put_fd(proc, NULL, m_in->m_type);
203 	else
204 		put_result(proc);
205 }
206 
207 static int
208 vfs_creat_out(struct trace_proc * proc, const message * m_out)
209 {
210 
211 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_creat.name,
212 	    m_out->m_lc_vfs_creat.len);
213 	put_open_flags(proc, "flags", m_out->m_lc_vfs_creat.flags,
214 	    TRUE /*full*/);
215 	put_mode(proc, "mode", m_out->m_lc_vfs_creat.mode);
216 
217 	return CT_DONE;
218 }
219 
220 static int
221 vfs_close_out(struct trace_proc * proc, const message * m_out)
222 {
223 
224 	put_fd(proc, "fd", m_out->m_lc_vfs_close.fd);
225 
226 	return CT_DONE;
227 }
228 
229 /* This function is used for link, rename, and symlink. */
230 static int
231 vfs_link_out(struct trace_proc * proc, const message * m_out)
232 {
233 
234 	put_buf(proc, "path1", PF_PATH, m_out->m_lc_vfs_link.name1,
235 	    m_out->m_lc_vfs_link.len1);
236 	put_buf(proc, "path2", PF_PATH, m_out->m_lc_vfs_link.name2,
237 	    m_out->m_lc_vfs_link.len2);
238 
239 	return CT_DONE;
240 }
241 
242 static int
243 vfs_path_out(struct trace_proc * proc, const message * m_out)
244 {
245 
246 	put_path(proc, m_out);
247 
248 	return CT_DONE;
249 }
250 
251 static int
252 vfs_path_mode_out(struct trace_proc * proc, const message * m_out)
253 {
254 
255 	put_path(proc, m_out);
256 	put_mode(proc, "mode", m_out->m_lc_vfs_path.mode);
257 
258 	return CT_DONE;
259 }
260 
261 void
262 put_dev(struct trace_proc * proc, const char * name, dev_t dev)
263 {
264 	devmajor_t major;
265 	devminor_t minor;
266 
267 	major = major(dev);
268 	minor = minor(dev);
269 
270 	/* The value 0 ("no device") should print as "0". */
271 	if (dev != 0 && makedev(major, minor) == dev && !valuesonly)
272 		put_value(proc, name, "<%d,%d>", major, minor);
273 	else
274 		put_value(proc, name, "%"PRIu64, dev);
275 }
276 
277 static int
278 vfs_mknod_out(struct trace_proc * proc, const message * m_out)
279 {
280 
281 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mknod.name,
282 	    m_out->m_lc_vfs_mknod.len);
283 	put_mode(proc, "mode", m_out->m_lc_vfs_mknod.mode);
284 	put_dev(proc, "dev", m_out->m_lc_vfs_mknod.device);
285 
286 	return CT_DONE;
287 }
288 
289 static int
290 vfs_chown_out(struct trace_proc * proc, const message * m_out)
291 {
292 
293 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_chown.name,
294 	    m_out->m_lc_vfs_chown.len);
295 	/* -1 means "keep the current value" so print as signed */
296 	put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner);
297 	put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group);
298 
299 	return CT_DONE;
300 }
301 
302 /* TODO: expand this to the full ST_ set. */
303 static const struct flags mount_flags[] = {
304 	FLAG(MNT_RDONLY),
305 };
306 
307 static int
308 vfs_mount_out(struct trace_proc * proc, const message * m_out)
309 {
310 
311 	put_buf(proc, "special", PF_PATH, m_out->m_lc_vfs_mount.dev,
312 	    m_out->m_lc_vfs_mount.devlen);
313 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mount.path,
314 	    m_out->m_lc_vfs_mount.pathlen);
315 	put_flags(proc, "flags", mount_flags, COUNT(mount_flags), "0x%x",
316 	    m_out->m_lc_vfs_mount.flags);
317 	put_buf(proc, "type", PF_STRING, m_out->m_lc_vfs_mount.type,
318 	    m_out->m_lc_vfs_mount.typelen);
319 	put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_mount.label,
320 	    m_out->m_lc_vfs_mount.labellen);
321 
322 	return CT_DONE;
323 }
324 
325 static int
326 vfs_umount_out(struct trace_proc * proc, const message * m_out)
327 {
328 
329 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_umount.name,
330 	    m_out->m_lc_vfs_umount.namelen);
331 
332 	return CT_DONE;
333 }
334 
335 static void
336 vfs_umount_in(struct trace_proc * proc, const message * m_out,
337 	const message * __unused m_in, int failed)
338 {
339 
340 	put_result(proc);
341 
342 	if (!failed) {
343 		put_open(proc, NULL, 0, "(", ", ");
344 		put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_umount.label,
345 		    m_out->m_lc_vfs_umount.labellen);
346 
347 		put_close(proc, ")");
348 	}
349 }
350 
351 
352 static const struct flags access_flags[] = {
353 	FLAG_ZERO(F_OK),
354 	FLAG(R_OK),
355 	FLAG(W_OK),
356 	FLAG(X_OK),
357 };
358 
359 static int
360 vfs_access_out(struct trace_proc * proc, const message * m_out)
361 {
362 
363 	put_path(proc, m_out);
364 	put_flags(proc, "mode", access_flags, COUNT(access_flags), "0x%x",
365 	    m_out->m_lc_vfs_path.mode);
366 
367 	return CT_DONE;
368 }
369 
370 static int
371 vfs_readlink_out(struct trace_proc * proc, const message * m_out)
372 {
373 
374 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_readlink.name,
375 	    m_out->m_lc_vfs_readlink.namelen);
376 
377 	return CT_NOTDONE;
378 }
379 
380 static void
381 vfs_readlink_in(struct trace_proc * proc, const message * m_out,
382 	const message * m_in, int failed)
383 {
384 
385 	/* The call does not return a string, so do not use PF_STRING here. */
386 	put_buf(proc, "buf", failed, m_out->m_lc_vfs_readlink.buf,
387 	    m_in->m_type);
388 	put_value(proc, "bufsize", "%zd", m_out->m_lc_vfs_readlink.bufsize);
389 	put_equals(proc);
390 	put_result(proc);
391 }
392 
393 static void
394 put_struct_stat(struct trace_proc * proc, const char * name, int flags,
395 	vir_bytes addr)
396 {
397 	struct stat buf;
398 	int is_special;
399 
400 	if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
401 		return;
402 
403 	/*
404 	 * The combination of struct stat's frequent usage and large number of
405 	 * fields makes this structure a pain to print.  For now, the idea is
406 	 * that for verbosity level 0, we print the mode, and the target device
407 	 * for block/char special files or the file size for all other files.
408 	 * For higher verbosity levels, largely maintain the structure's own
409 	 * order of fields.  Violate this general structure printing rule for
410 	 * some fields though, because the actual field order in struct stat is
411 	 * downright ridiculous.  Like elsewhere, for verbosity level 1 print
412 	 * all fields with meaningful values, and for verbosity level 2 just
413 	 * print everything, including fields that are known to be not yet
414 	 * supported and fields that contain known values.
415 	 */
416 	is_special = (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode));
417 
418 	if (verbose > 0) {
419 		put_dev(proc, "st_dev", buf.st_dev);
420 		put_value(proc, "st_ino", "%"PRId64, buf.st_ino);
421 	}
422 	put_mode(proc, "st_mode", buf.st_mode);
423 	if (verbose > 0) {
424 		put_value(proc, "st_nlink", "%u", buf.st_nlink);
425 		put_value(proc, "st_uid", "%u", buf.st_uid);
426 		put_value(proc, "st_gid", "%u", buf.st_gid);
427 	}
428 	if (is_special || verbose > 1)
429 		put_dev(proc, "st_rdev", buf.st_rdev);
430 	if (verbose > 0) {
431 		/*
432 		 * TODO: print the nanosecond part, but possibly only if we are
433 		 * not actually interpreting the time as a date (another TODO),
434 		 * and/or possibly only with verbose > 1 (largely unsupported).
435 		 */
436 		put_time(proc, "st_atime", buf.st_atime);
437 		put_time(proc, "st_mtime", buf.st_mtime);
438 		put_time(proc, "st_ctime", buf.st_ctime);
439 	}
440 	if (verbose > 1) /* not yet supported on MINIX3 */
441 		put_time(proc, "st_birthtime", buf.st_birthtime);
442 	if (!is_special || verbose > 1)
443 		put_value(proc, "st_size", "%"PRId64, buf.st_size);
444 	if (verbose > 0) {
445 		put_value(proc, "st_blocks", "%"PRId64, buf.st_blocks);
446 		put_value(proc, "st_blksize", "%"PRId32, buf.st_blksize);
447 	}
448 	if (verbose > 1) {
449 		put_value(proc, "st_flags", "%"PRIu32, buf.st_flags);
450 		put_value(proc, "st_gen", "%"PRIu32, buf.st_gen);
451 	}
452 
453 	put_close_struct(proc, verbose > 1);
454 }
455 
456 static int
457 vfs_stat_out(struct trace_proc * proc, const message * m_out)
458 {
459 
460 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_stat.name,
461 	    m_out->m_lc_vfs_stat.len);
462 
463 	return CT_NOTDONE;
464 }
465 
466 static void
467 vfs_stat_in(struct trace_proc * proc, const message * m_out,
468 	const message * __unused m_in, int failed)
469 {
470 
471 	put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_stat.buf);
472 	put_equals(proc);
473 	put_result(proc);
474 }
475 
476 static int
477 vfs_fstat_out(struct trace_proc * proc, const message * m_out)
478 {
479 
480 	put_fd(proc, "fd", m_out->m_lc_vfs_fstat.fd);
481 
482 	return CT_NOTDONE;
483 }
484 
485 static void
486 vfs_fstat_in(struct trace_proc * proc, const message * m_out,
487 	const message * __unused m_in, int failed)
488 {
489 
490 	put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_fstat.buf);
491 	put_equals(proc);
492 	put_result(proc);
493 }
494 
495 static int
496 vfs_ioctl_out(struct trace_proc * proc, const message * m_out)
497 {
498 
499 	put_fd(proc, "fd", m_out->m_lc_vfs_ioctl.fd);
500 	put_ioctl_req(proc, "req", m_out->m_lc_vfs_ioctl.req,
501 	    FALSE /*is_svrctl*/);
502 	return put_ioctl_arg_out(proc, "arg", m_out->m_lc_vfs_ioctl.req,
503 	    (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/);
504 }
505 
506 static void
507 vfs_ioctl_in(struct trace_proc * proc, const message * m_out,
508 	const message * __unused m_in, int failed)
509 {
510 
511 	put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_vfs_ioctl.req,
512 	    (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/);
513 }
514 
515 static void
516 put_fcntl_cmd(struct trace_proc * proc, const char * name, int cmd)
517 {
518 	const char *text = NULL;
519 
520 	if (!valuesonly) {
521 		switch (cmd) {
522 		TEXT(F_DUPFD);
523 		TEXT(F_GETFD);
524 		TEXT(F_SETFD);
525 		TEXT(F_GETFL);
526 		TEXT(F_SETFL);
527 		TEXT(F_GETOWN);
528 		TEXT(F_SETOWN);
529 		TEXT(F_GETLK);
530 		TEXT(F_SETLK);
531 		TEXT(F_SETLKW);
532 		TEXT(F_CLOSEM);
533 		TEXT(F_MAXFD);
534 		TEXT(F_DUPFD_CLOEXEC);
535 		TEXT(F_GETNOSIGPIPE);
536 		TEXT(F_SETNOSIGPIPE);
537 		TEXT(F_FREESP);
538 		TEXT(F_FLUSH_FS_CACHE);
539 		}
540 	}
541 
542 	if (text != NULL)
543 		put_field(proc, name, text);
544 	else
545 		put_value(proc, name, "%d", cmd);
546 }
547 
548 static const struct flags fd_flags[] = {
549 	FLAG(FD_CLOEXEC),
550 };
551 
552 #define put_fd_flags(p, n, v) \
553 	put_flags(p, n, fd_flags, COUNT(fd_flags), "0x%x", v)
554 
555 static void
556 put_flock_type(struct trace_proc * proc, const char * name, int type)
557 {
558 	const char *text = NULL;
559 
560 	if (!valuesonly) {
561 		switch (type) {
562 		TEXT(F_RDLCK);
563 		TEXT(F_UNLCK);
564 		TEXT(F_WRLCK);
565 		}
566 	}
567 
568 	if (text != NULL)
569 		put_field(proc, name, text);
570 	else
571 		put_value(proc, name, "%d", type);
572 }
573 
574 /*
575  * With PF_FULL, also print l_pid, unless l_type is F_UNLCK in which case
576  * only that type is printed.   With PF_ALT, print only l_whence/l_start/l_len.
577  */
578 static void
579 put_struct_flock(struct trace_proc * proc, const char * name, int flags,
580 	vir_bytes addr)
581 {
582 	struct flock flock;
583 	int limited;
584 
585 	if (!put_open_struct(proc, name, flags, addr, &flock, sizeof(flock)))
586 		return;
587 
588 	limited = ((flags & PF_FULL) && flock.l_type == F_UNLCK);
589 
590 	if (!(flags & PF_ALT))
591 		put_flock_type(proc, "l_type", flock.l_type);
592 	if (!limited) {
593 		put_lseek_whence(proc, "l_whence", flock.l_whence);
594 		put_value(proc, "l_start", "%"PRId64, flock.l_start);
595 		put_value(proc, "l_len", "%"PRId64, flock.l_len);
596 		if (flags & PF_FULL)
597 			put_value(proc, "l_pid", "%d", flock.l_pid);
598 	}
599 
600 	put_close_struct(proc, TRUE /*all*/);
601 }
602 
603 static int
604 vfs_fcntl_out(struct trace_proc * proc, const message * m_out)
605 {
606 
607 	put_fd(proc, "fd", m_out->m_lc_vfs_fcntl.fd);
608 	put_fcntl_cmd(proc, "cmd", m_out->m_lc_vfs_fcntl.cmd);
609 
610 	switch (m_out->m_lc_vfs_fcntl.cmd) {
611 	case F_DUPFD:
612 	case F_DUPFD_CLOEXEC:
613 		put_fd(proc, "fd2", m_out->m_lc_vfs_fcntl.arg_int);
614 		break;
615 	case F_SETFD:
616 		put_fd_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int);
617 		break;
618 	case F_SETFL:
619 		/*
620 		 * One of those difficult cases: the access mode is ignored, so
621 		 * we don't want to print O_RDONLY if it is not given.  On the
622 		 * other hand, fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_..) is
623 		 * a fairly common construction, in which case we don't want to
624 		 * print eg O_..|0x2 if the access mode is O_RDWR.  Thus, we
625 		 * compromise: show the access mode if any of its bits are set.
626 		 */
627 		put_open_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int,
628 		    m_out->m_lc_vfs_fcntl.arg_int & O_ACCMODE /*full*/);
629 		break;
630 	case F_SETLK:
631 	case F_SETLKW:
632 		put_struct_flock(proc, "lkp", 0,
633 		    m_out->m_lc_vfs_fcntl.arg_ptr);
634 		break;
635 	case F_FREESP:
636 		put_struct_flock(proc, "lkp", PF_ALT,
637 		    m_out->m_lc_vfs_fcntl.arg_ptr);
638 		break;
639 	case F_SETNOSIGPIPE:
640 		put_value(proc, "arg", "%d", m_out->m_lc_vfs_fcntl.arg_int);
641 		break;
642 	}
643 
644 	return (m_out->m_lc_vfs_fcntl.cmd != F_GETLK) ? CT_DONE : CT_NOTDONE;
645 }
646 
647 static void
648 vfs_fcntl_in(struct trace_proc * proc, const message * m_out,
649 	const message * m_in, int failed)
650 {
651 
652 	switch (m_out->m_lc_vfs_fcntl.cmd) {
653 	case F_GETFD:
654 		if (failed)
655 			break;
656 		put_fd_flags(proc, NULL, m_in->m_type);
657 		return;
658 	case F_GETFL:
659 		if (failed)
660 			break;
661 		put_open_flags(proc, NULL, m_in->m_type, TRUE /*full*/);
662 		return;
663 	case F_GETLK:
664 		put_struct_flock(proc, "lkp", failed | PF_FULL,
665 		    m_out->m_lc_vfs_fcntl.arg_ptr);
666 		put_equals(proc);
667 		break;
668 	}
669 
670 	put_result(proc);
671 }
672 
673 static int
674 vfs_pipe2_out(struct trace_proc * __unused proc,
675 	const message * __unused m_out)
676 {
677 
678 	return CT_NOTDONE;
679 }
680 
681 static void
682 vfs_pipe2_in(struct trace_proc * proc, const message * m_out,
683 	const message * m_in, int failed)
684 {
685 
686 	if (!failed) {
687 		put_open(proc, "fd", PF_NONAME, "[", ", ");
688 		put_fd(proc, "rfd", m_in->m_vfs_lc_fdpair.fd0);
689 		put_fd(proc, "wfd", m_in->m_vfs_lc_fdpair.fd1);
690 		put_close(proc, "]");
691 	} else
692 		put_field(proc, "fd", "&..");
693 	put_open_flags(proc, "flags", m_out->m_lc_vfs_pipe2.flags,
694 	    FALSE /*full*/);
695 	put_equals(proc);
696 	put_result(proc);
697 }
698 
699 static int
700 vfs_umask_out(struct trace_proc * proc, const message * m_out)
701 {
702 
703 	put_mode(proc, NULL, m_out->m_lc_vfs_umask.mask);
704 
705 	return CT_DONE;
706 }
707 
708 static void
709 vfs_umask_in(struct trace_proc * proc, const message * __unused m_out,
710 	const message * m_in, int failed)
711 {
712 
713 	if (!failed)
714 		put_mode(proc, NULL, m_in->m_type);
715 	else
716 		put_result(proc);
717 
718 }
719 
720 static void
721 put_dirent_type(struct trace_proc * proc, const char * name, unsigned int type)
722 {
723 	const char *text = NULL;
724 
725 	if (!valuesonly) {
726 		switch (type) {
727 		TEXT(DT_UNKNOWN);
728 		TEXT(DT_FIFO);
729 		TEXT(DT_CHR);
730 		TEXT(DT_DIR);
731 		TEXT(DT_BLK);
732 		TEXT(DT_REG);
733 		TEXT(DT_LNK);
734 		TEXT(DT_SOCK);
735 		TEXT(DT_WHT);
736 		}
737 	}
738 
739 	if (text != NULL)
740 		put_field(proc, name, text);
741 	else
742 		put_value(proc, name, "%u", type);
743 }
744 
745 static void
746 put_struct_dirent(struct trace_proc * proc, const char *name, int flags,
747 	vir_bytes addr)
748 {
749 	struct dirent dirent;
750 
751 	if (!put_open_struct(proc, name, flags, addr, &dirent, sizeof(dirent)))
752 		return;
753 
754 	if (verbose > 0)
755 		put_value(proc, "d_fileno", "%"PRIu64, dirent.d_fileno);
756 	if (verbose > 1) {
757 		put_value(proc, "d_reclen", "%u", dirent.d_reclen);
758 		put_value(proc, "d_namlen", "%u", dirent.d_namlen);
759 	}
760 	if (verbose >= 1 + (dirent.d_type == DT_UNKNOWN))
761 		put_dirent_type(proc, "d_type", dirent.d_type);
762 	put_buf(proc, "d_name", PF_LOCADDR, (vir_bytes)dirent.d_name,
763 	    MIN(dirent.d_namlen, sizeof(dirent.d_name)));
764 
765 	put_close_struct(proc, verbose > 1);
766 }
767 
768 static void
769 put_dirent_array(struct trace_proc * proc, const char * name, int flags,
770 	vir_bytes addr, ssize_t size)
771 {
772 	struct dirent dirent;
773 	unsigned count, max;
774 	ssize_t off, chunk;
775 
776 	if ((flags & PF_FAILED) || valuesonly > 1 || size < 0) {
777 		put_ptr(proc, name, addr);
778 
779 		return;
780 	}
781 
782 	if (size == 0) {
783 		put_field(proc, name, "[]");
784 
785 		return;
786 	}
787 
788 	if (verbose == 0)
789 		max = 0; /* TODO: should we set this to 1 instead? */
790 	else if (verbose == 1)
791 		max = 3; /* low; just to give an indication where we are */
792 	else
793 		max = INT_MAX;
794 
795 	/*
796 	 * TODO: as is, this is highly inefficient, as we are typically copying
797 	 * in the same pieces of memory in repeatedly..
798 	 */
799 	count = 0;
800 	for (off = 0; off < size; off += chunk) {
801 		chunk = size - off;
802 		if ((size_t)chunk > sizeof(dirent))
803 			chunk = (ssize_t)sizeof(dirent);
804 		if ((size_t)chunk < _DIRENT_MINSIZE(&dirent))
805 			break;
806 
807 		if (mem_get_data(proc->pid, addr + off, &dirent, chunk) < 0) {
808 			if (off == 0) {
809 				put_ptr(proc, name, addr);
810 
811 				return;
812 			}
813 
814 			break;
815 		}
816 
817 		if (off == 0)
818 			put_open(proc, name, PF_NONAME, "[", ", ");
819 
820 		if (count < max)
821 			put_struct_dirent(proc, NULL, PF_LOCADDR,
822 			    (vir_bytes)&dirent);
823 
824 		if (chunk > dirent.d_reclen)
825 			chunk = dirent.d_reclen;
826 		count++;
827 	}
828 
829 	if (off < size)
830 		put_tail(proc, 0, 0);
831 	else if (count > max)
832 		put_tail(proc, count, max);
833 	put_close(proc, "]");
834 }
835 
836 static int
837 vfs_getdents_out(struct trace_proc * proc, const message * m_out)
838 {
839 
840 	put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
841 
842 	return CT_NOTDONE;
843 }
844 
845 static void
846 vfs_getdents_in(struct trace_proc * proc, const message * m_out,
847 	const message * m_in, int failed)
848 {
849 
850 	put_dirent_array(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf,
851 	    m_in->m_type);
852 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
853 	put_equals(proc);
854 	put_result(proc);
855 }
856 
857 static void
858 put_fd_set(struct trace_proc * proc, const char * name, vir_bytes addr,
859 	int nfds)
860 {
861 	fd_set set;
862 	size_t off;
863 	unsigned int i, j, words, count, max;
864 
865 	if (addr == 0 || nfds < 0) {
866 		put_ptr(proc, name, addr);
867 
868 		return;
869 	}
870 
871 	/*
872 	 * Each process may define its own FD_SETSIZE, so our fd_set may be of
873 	 * a different size than theirs.  Thus, we copy at a granularity known
874 	 * to be valid in any case: a single word of bits.  We make the
875 	 * assumption that fd_set consists purely of bits, so that we can use
876 	 * the second (and so on) bit word as an fd_set by itself.
877 	 */
878 	words = (nfds + NFDBITS - 1) / NFDBITS;
879 
880 	count = 0;
881 
882 	if (verbose == 0)
883 		max = 16;
884 	else if (verbose == 1)
885 		max = FD_SETSIZE;
886 	else
887 		max = INT_MAX;
888 
889 	/* TODO: copy in more at once, but stick to fd_mask boundaries. */
890 	for (off = 0, i = 0; i < words; i++, off += sizeof(fd_mask)) {
891 		if (mem_get_data(proc->pid, addr + off, &set,
892 		    sizeof(fd_mask)) != 0) {
893 			if (count == 0) {
894 				put_ptr(proc, name, addr);
895 
896 				return;
897 			}
898 
899 			break;
900 		}
901 
902 		for (j = 0; j < NFDBITS; j++) {
903 			if (FD_ISSET(j, &set)) {
904 				if (count == 0)
905 					put_open(proc, name, PF_NONAME, "[",
906 					    " ");
907 
908 				if (count < max)
909 					put_fd(proc, NULL, i * NFDBITS + j);
910 
911 				count++;
912 			}
913 		}
914 	}
915 
916 	/*
917 	 * The empty set should print as "[]".  If copying any part failed, it
918 	 * should print as "[x, ..(?)]" where x is the set printed so far, if
919 	 * any.  If copying never failed, and we did not print all fds in the
920 	 * set, print the remaining count n as "[x, ..(+n)]" at the end.
921 	 */
922 	if (count == 0)
923 		put_open(proc, name, PF_NONAME, "[", " ");
924 
925 	if (i < words)
926 		put_tail(proc, 0, 0);
927 	else if (count > max)
928 		put_tail(proc, count, max);
929 
930 	put_close(proc, "]");
931 }
932 
933 static int
934 vfs_select_out(struct trace_proc * proc, const message * m_out)
935 {
936 	int nfds;
937 
938 	nfds = m_out->m_lc_vfs_select.nfds;
939 
940 	put_fd(proc, "nfds", nfds); /* not really a file descriptor.. */
941 	put_fd_set(proc, "readfds",
942 	    (vir_bytes)m_out->m_lc_vfs_select.readfds, nfds);
943 	put_fd_set(proc, "writefds",
944 	    (vir_bytes)m_out->m_lc_vfs_select.writefds, nfds);
945 	put_fd_set(proc, "errorfds",
946 	    (vir_bytes)m_out->m_lc_vfs_select.errorfds, nfds);
947 	put_struct_timeval(proc, "timeout", 0, m_out->m_lc_vfs_select.timeout);
948 
949 	return CT_DONE;
950 }
951 
952 static void
953 vfs_select_in(struct trace_proc * proc, const message * m_out,
954 	const message * __unused m_in, int failed)
955 {
956 	vir_bytes readfds, writefds, errorfds;
957 	int nfds;
958 
959 	put_result(proc);
960 	if (failed)
961 		return;
962 
963 	nfds = m_out->m_lc_vfs_select.nfds;
964 
965 	readfds = (vir_bytes)m_out->m_lc_vfs_select.readfds;
966 	writefds = (vir_bytes)m_out->m_lc_vfs_select.writefds;
967 	errorfds = (vir_bytes)m_out->m_lc_vfs_select.errorfds;
968 
969 	if (readfds == 0 && writefds == 0 && errorfds == 0)
970 		return;
971 
972 	/* Omit names, because it looks weird. */
973 	put_open(proc, NULL, PF_NONAME, "(", ", ");
974 	if (readfds != 0)
975 		put_fd_set(proc, "readfds", readfds, nfds);
976 	if (writefds != 0)
977 		put_fd_set(proc, "writefds", writefds, nfds);
978 	if (errorfds != 0)
979 		put_fd_set(proc, "errorfds", errorfds, nfds);
980 	put_close(proc, ")");
981 }
982 
983 static int
984 vfs_fchdir_out(struct trace_proc * proc, const message * m_out)
985 {
986 
987 	put_fd(proc, "fd", m_out->m_lc_vfs_fchdir.fd);
988 
989 	return CT_DONE;
990 }
991 
992 static int
993 vfs_fsync_out(struct trace_proc * proc, const message * m_out)
994 {
995 
996 	put_fd(proc, "fd", m_out->m_lc_vfs_fsync.fd);
997 
998 	return CT_DONE;
999 }
1000 
1001 static int
1002 vfs_truncate_out(struct trace_proc * proc, const message * m_out)
1003 {
1004 
1005 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_truncate.name,
1006 	    m_out->m_lc_vfs_truncate.len);
1007 	put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset);
1008 
1009 	return CT_DONE;
1010 }
1011 
1012 static int
1013 vfs_ftruncate_out(struct trace_proc * proc, const message * m_out)
1014 {
1015 
1016 	put_fd(proc, "fd", m_out->m_lc_vfs_truncate.fd);
1017 	put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset);
1018 
1019 	return CT_DONE;
1020 }
1021 
1022 static int
1023 vfs_fchmod_out(struct trace_proc * proc, const message * m_out)
1024 {
1025 
1026 	put_fd(proc, "fd", m_out->m_lc_vfs_fchmod.fd);
1027 	put_mode(proc, "mode", m_out->m_lc_vfs_fchmod.mode);
1028 
1029 	return CT_DONE;
1030 }
1031 
1032 static int
1033 vfs_fchown_out(struct trace_proc * proc, const message * m_out)
1034 {
1035 
1036 	put_fd(proc, "fd", m_out->m_lc_vfs_chown.fd);
1037 	/* -1 means "keep the current value" so print as signed */
1038 	put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner);
1039 	put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group);
1040 
1041 	return CT_DONE;
1042 }
1043 
1044 static const char *
1045 vfs_utimens_name(const message * m_out)
1046 {
1047 	int has_path, has_flags;
1048 
1049 	has_path = (m_out->m_vfs_utimens.name != NULL);
1050 	has_flags = (m_out->m_vfs_utimens.flags != 0);
1051 
1052 	if (has_path && m_out->m_vfs_utimens.flags == AT_SYMLINK_NOFOLLOW)
1053 		return "lutimens";
1054 	if (has_path && !has_flags)
1055 		return "utimens";
1056 	else if (!has_path && !has_flags)
1057 		return "futimens";
1058 	else
1059 		return "utimensat";
1060 }
1061 
1062 static const struct flags at_flags[] = {
1063 	FLAG(AT_EACCESS),
1064 	FLAG(AT_SYMLINK_NOFOLLOW),
1065 	FLAG(AT_SYMLINK_FOLLOW),
1066 	FLAG(AT_REMOVEDIR),
1067 };
1068 
1069 static void
1070 put_utimens_timespec(struct trace_proc * proc, const char * name,
1071 	time_t sec, long nsec)
1072 {
1073 
1074 	/* No field names. */
1075 	put_open(proc, name, PF_NONAME, "{", ", ");
1076 
1077 	put_time(proc, "tv_sec", sec);
1078 
1079 	if (!valuesonly && nsec == UTIME_NOW)
1080 		put_field(proc, "tv_nsec", "UTIME_NOW");
1081 	else if (!valuesonly && nsec == UTIME_OMIT)
1082 		put_field(proc, "tv_nsec", "UTIME_OMIT");
1083 	else
1084 		put_value(proc, "tv_nsec", "%ld", nsec);
1085 
1086 	put_close(proc, "}");
1087 }
1088 
1089 static int
1090 vfs_utimens_out(struct trace_proc * proc, const message * m_out)
1091 {
1092 	int has_path, has_flags;
1093 
1094 	/* Here we do not care about the utimens/lutimens distinction. */
1095 	has_path = (m_out->m_vfs_utimens.name != NULL);
1096 	has_flags = !!(m_out->m_vfs_utimens.flags & ~AT_SYMLINK_NOFOLLOW);
1097 
1098 	if (has_path && has_flags)
1099 		put_field(proc, "fd", "AT_CWD"); /* utimensat */
1100 	else if (!has_path)
1101 		put_fd(proc, "fd", m_out->m_vfs_utimens.fd); /* futimes */
1102 	if (has_path || has_flags) /* lutimes, utimes, utimensat */
1103 		put_buf(proc, "path", PF_PATH,
1104 		    (vir_bytes)m_out->m_vfs_utimens.name,
1105 		    m_out->m_vfs_utimens.len);
1106 
1107 	put_open(proc, "times", 0, "[", ", ");
1108 	put_utimens_timespec(proc, "atime", m_out->m_vfs_utimens.atime,
1109 	    m_out->m_vfs_utimens.ansec);
1110 	put_utimens_timespec(proc, "mtime", m_out->m_vfs_utimens.mtime,
1111 	    m_out->m_vfs_utimens.mnsec);
1112 	put_close(proc, "]");
1113 
1114 	if (has_flags)
1115 		put_flags(proc, "flag", at_flags, COUNT(at_flags), "0x%x",
1116 		    m_out->m_vfs_utimens.flags);
1117 
1118 	return CT_DONE;
1119 }
1120 
1121 static const struct flags statvfs_flags[] = {
1122 	FLAG(ST_WAIT),
1123 	FLAG(ST_NOWAIT),
1124 };
1125 
1126 static const struct flags st_flags[] = {
1127 	FLAG(ST_RDONLY),
1128 	FLAG(ST_SYNCHRONOUS),
1129 	FLAG(ST_NOEXEC),
1130 	FLAG(ST_NOSUID),
1131 	FLAG(ST_NODEV),
1132 	FLAG(ST_UNION),
1133 	FLAG(ST_ASYNC),
1134 	FLAG(ST_NOCOREDUMP),
1135 	FLAG(ST_RELATIME),
1136 	FLAG(ST_IGNORE),
1137 	FLAG(ST_NOATIME),
1138 	FLAG(ST_SYMPERM),
1139 	FLAG(ST_NODEVMTIME),
1140 	FLAG(ST_SOFTDEP),
1141 	FLAG(ST_LOG),
1142 	FLAG(ST_EXTATTR),
1143 	FLAG(ST_EXRDONLY),
1144 	FLAG(ST_EXPORTED),
1145 	FLAG(ST_DEFEXPORTED),
1146 	FLAG(ST_EXPORTANON),
1147 	FLAG(ST_EXKERB),
1148 	FLAG(ST_EXNORESPORT),
1149 	FLAG(ST_EXPUBLIC),
1150 	FLAG(ST_LOCAL),
1151 	FLAG(ST_QUOTA),
1152 	FLAG(ST_ROOTFS),
1153 	FLAG(ST_NOTRUNC),
1154 };
1155 
1156 static void
1157 put_struct_statvfs(struct trace_proc * proc, const char * name, int flags,
1158 	vir_bytes addr)
1159 {
1160 	struct statvfs buf;
1161 
1162 	if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
1163 		return;
1164 
1165 	put_flags(proc, "f_flag", st_flags, COUNT(st_flags), "0x%x",
1166 	    buf.f_flag);
1167 	put_value(proc, "f_bsize", "%lu", buf.f_bsize);
1168 	if (verbose > 0 || buf.f_bsize != buf.f_frsize)
1169 		put_value(proc, "f_frsize", "%lu", buf.f_frsize);
1170 	if (verbose > 1)
1171 		put_value(proc, "f_iosize", "%lu", buf.f_iosize);
1172 
1173 	put_value(proc, "f_blocks", "%"PRIu64, buf.f_blocks);
1174 	put_value(proc, "f_bfree", "%"PRIu64, buf.f_bfree);
1175 	if (verbose > 1) {
1176 		put_value(proc, "f_bavail", "%"PRIu64, buf.f_bavail);
1177 		put_value(proc, "f_bresvd", "%"PRIu64, buf.f_bresvd);
1178 	}
1179 
1180 	if (verbose > 0) {
1181 		put_value(proc, "f_files", "%"PRIu64, buf.f_files);
1182 		put_value(proc, "f_ffree", "%"PRIu64, buf.f_ffree);
1183 	}
1184 	if (verbose > 1) {
1185 		put_value(proc, "f_favail", "%"PRIu64, buf.f_favail);
1186 		put_value(proc, "f_fresvd", "%"PRIu64, buf.f_fresvd);
1187 	}
1188 
1189 	if (verbose > 1) {
1190 		put_value(proc, "f_syncreads", "%"PRIu64, buf.f_syncreads);
1191 		put_value(proc, "f_syncwrites", "%"PRIu64, buf.f_syncwrites);
1192 		put_value(proc, "f_asyncreads", "%"PRIu64, buf.f_asyncreads);
1193 		put_value(proc, "f_asyncwrites", "%"PRIu64, buf.f_asyncwrites);
1194 
1195 		put_value(proc, "f_fsidx", "<%"PRId32",%"PRId32">",
1196 		    buf.f_fsidx.__fsid_val[0], buf.f_fsidx.__fsid_val[1]);
1197 	}
1198 	put_dev(proc, "f_fsid", buf.f_fsid); /* MINIX3 interpretation! */
1199 
1200 	if (verbose > 0)
1201 		put_value(proc, "f_namemax", "%lu", buf.f_namemax);
1202 	if (verbose > 1)
1203 		put_value(proc, "f_owner", "%u", buf.f_owner);
1204 
1205 	put_buf(proc, "f_fstypename", PF_STRING | PF_LOCADDR,
1206 	    (vir_bytes)&buf.f_fstypename, sizeof(buf.f_fstypename));
1207 	if (verbose > 0)
1208 		put_buf(proc, "f_mntfromname", PF_STRING | PF_LOCADDR,
1209 		    (vir_bytes)&buf.f_mntfromname, sizeof(buf.f_mntfromname));
1210 	put_buf(proc, "f_mntonname", PF_STRING | PF_LOCADDR,
1211 	    (vir_bytes)&buf.f_mntonname, sizeof(buf.f_mntonname));
1212 
1213 	put_close_struct(proc, verbose > 1);
1214 }
1215 
1216 static void
1217 put_statvfs_array(struct trace_proc * proc, const char * name, int flags,
1218 	vir_bytes addr, int count)
1219 {
1220 	struct statvfs buf;
1221 	int i, max;
1222 
1223 	if ((flags & PF_FAILED) || valuesonly > 1 || count < 0) {
1224 		put_ptr(proc, name, addr);
1225 
1226 		return;
1227 	}
1228 
1229 	if (count == 0) {
1230 		put_field(proc, name, "[]");
1231 
1232 		return;
1233 	}
1234 
1235 	if (verbose == 0)
1236 		max = 0;
1237 	else if (verbose == 1)
1238 		max = 1; /* TODO: is this reasonable? */
1239 	else
1240 		max = INT_MAX;
1241 
1242 	if (max > count)
1243 		max = count;
1244 
1245 	for (i = 0; i < max; i++) {
1246 		if (mem_get_data(proc->pid, addr + i * sizeof(buf), &buf,
1247 		    sizeof(buf)) < 0) {
1248 			if (i == 0) {
1249 				put_ptr(proc, name, addr);
1250 
1251 				return;
1252 			}
1253 
1254 			break;
1255 		}
1256 
1257 		if (i == 0)
1258 			put_open(proc, name, PF_NONAME, "[", ", ");
1259 
1260 		put_struct_statvfs(proc, NULL, PF_LOCADDR, (vir_bytes)&buf);
1261 	}
1262 
1263 	if (i == 0)
1264 		put_open(proc, name, PF_NONAME, "[", ", ");
1265 	if (i < max)
1266 		put_tail(proc, 0, 0);
1267 	else if (count > i)
1268 		put_tail(proc, count, i);
1269 	put_close(proc, "]");
1270 }
1271 
1272 static int
1273 vfs_getvfsstat_out(struct trace_proc * proc, const message * m_out)
1274 {
1275 
1276 	if (m_out->m_lc_vfs_getvfsstat.buf == 0) {
1277 		put_ptr(proc, "buf", m_out->m_lc_vfs_getvfsstat.buf);
1278 		put_value(proc, "bufsize", "%zu",
1279 		    m_out->m_lc_vfs_getvfsstat.len);
1280 		put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags),
1281 		    "%d", m_out->m_lc_vfs_getvfsstat.flags);
1282 		return CT_DONE;
1283 	} else
1284 		return CT_NOTDONE;
1285 }
1286 
1287 static void
1288 vfs_getvfsstat_in(struct trace_proc * proc, const message * m_out,
1289 	const message * m_in, int failed)
1290 {
1291 
1292 	if (m_out->m_lc_vfs_getvfsstat.buf != 0) {
1293 		put_statvfs_array(proc, "buf", failed,
1294 		    m_out->m_lc_vfs_getvfsstat.buf, m_in->m_type);
1295 		put_value(proc, "bufsize", "%zu",
1296 		    m_out->m_lc_vfs_getvfsstat.len);
1297 		put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags),
1298 		    "%d", m_out->m_lc_vfs_getvfsstat.flags);
1299 		put_equals(proc);
1300 	}
1301 	put_result(proc);
1302 }
1303 
1304 static int
1305 vfs_statvfs1_out(struct trace_proc * proc, const message * m_out)
1306 {
1307 
1308 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_statvfs1.name,
1309 	    m_out->m_lc_vfs_statvfs1.len);
1310 
1311 	return CT_NOTDONE;
1312 }
1313 
1314 static void
1315 vfs_statvfs1_in(struct trace_proc * proc, const message * m_out,
1316 	const message * __unused m_in, int failed)
1317 {
1318 
1319 	put_struct_statvfs(proc, "buf", failed, m_out->m_lc_vfs_statvfs1.buf);
1320 	put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags), "%d",
1321 	    m_out->m_lc_vfs_statvfs1.flags);
1322 	put_equals(proc);
1323 	put_result(proc);
1324 }
1325 
1326 /* This function is shared between statvfs1 and fstatvfs1. */
1327 static int
1328 vfs_fstatvfs1_out(struct trace_proc * proc, const message * m_out)
1329 {
1330 
1331 	put_fd(proc, "fd", m_out->m_lc_vfs_statvfs1.fd);
1332 
1333 	return CT_NOTDONE;
1334 }
1335 
1336 static int
1337 vfs_svrctl_out(struct trace_proc * proc, const message * m_out)
1338 {
1339 
1340 	put_ioctl_req(proc, "request", m_out->m_lc_svrctl.request,
1341 	    TRUE /*is_svrctl*/);
1342 	return put_ioctl_arg_out(proc, "arg", m_out->m_lc_svrctl.request,
1343 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1344 }
1345 
1346 static void
1347 vfs_svrctl_in(struct trace_proc * proc, const message * m_out,
1348 	const message * __unused m_in, int failed)
1349 {
1350 
1351 	put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_svrctl.request,
1352 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1353 }
1354 
1355 static int
1356 vfs_gcov_flush_out(struct trace_proc * proc, const message * m_out)
1357 {
1358 
1359 	put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_gcov.label,
1360 	    m_out->m_lc_vfs_gcov.labellen);
1361 	put_ptr(proc, "buff", m_out->m_lc_vfs_gcov.buf);
1362 	put_value(proc, "buff_sz", "%zu", m_out->m_lc_vfs_gcov.buflen);
1363 
1364 	return CT_DONE;
1365 }
1366 
1367 void
1368 put_socket_family(struct trace_proc * proc, const char * name, int family)
1369 {
1370 	const char *text = NULL;
1371 
1372 	if (!valuesonly) {
1373 		/*
1374 		 * For socket(2) and socketpair(2) this should really be using
1375 		 * the prefix "PF_" since those functions take a protocol
1376 		 * family rather than an address family.  This rule is applied
1377 		 * fairly consistently within the system.  Here I caved because
1378 		 * I don't want to duplicate this entire function just for the
1379 		 * one letter.  There are exceptions however; some names only
1380 		 * exist as "PF_".
1381 		 */
1382 		switch (family) {
1383 		TEXT(AF_UNSPEC);
1384 		TEXT(AF_LOCAL);
1385 		TEXT(AF_INET);
1386 		TEXT(AF_IMPLINK);
1387 		TEXT(AF_PUP);
1388 		TEXT(AF_CHAOS);
1389 		TEXT(AF_NS);
1390 		TEXT(AF_ISO);
1391 		TEXT(AF_ECMA);
1392 		TEXT(AF_DATAKIT);
1393 		TEXT(AF_CCITT);
1394 		TEXT(AF_SNA);
1395 		TEXT(AF_DECnet);
1396 		TEXT(AF_DLI);
1397 		TEXT(AF_LAT);
1398 		TEXT(AF_HYLINK);
1399 		TEXT(AF_APPLETALK);
1400 		TEXT(AF_OROUTE);
1401 		TEXT(AF_LINK);
1402 		TEXT(PF_XTP);
1403 		TEXT(AF_COIP);
1404 		TEXT(AF_CNT);
1405 		TEXT(PF_RTIP);
1406 		TEXT(AF_IPX);
1407 		TEXT(AF_INET6);
1408 		TEXT(PF_PIP);
1409 		TEXT(AF_ISDN);
1410 		TEXT(AF_NATM);
1411 		TEXT(AF_ARP);
1412 		TEXT(PF_KEY);
1413 		TEXT(AF_BLUETOOTH);
1414 		TEXT(AF_IEEE80211);
1415 		TEXT(AF_MPLS);
1416 		TEXT(AF_ROUTE);
1417 		}
1418 	}
1419 
1420 	if (text != NULL)
1421 		put_field(proc, name, text);
1422 	else
1423 		put_value(proc, name, "%d", family);
1424 }
1425 
1426 static const struct flags socket_types[] = {
1427 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_STREAM),
1428 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_DGRAM),
1429 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RAW),
1430 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RDM),
1431 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_SEQPACKET),
1432 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_CONN_DGRAM),
1433 	FLAG(SOCK_CLOEXEC),
1434 	FLAG(SOCK_NONBLOCK),
1435 	FLAG(SOCK_NOSIGPIPE),
1436 };
1437 
1438 void
1439 put_socket_type(struct trace_proc * proc, const char * name, int type)
1440 {
1441 
1442 	put_flags(proc, name, socket_types, COUNT(socket_types), "%d", type);
1443 }
1444 
1445 static void
1446 put_socket_protocol(struct trace_proc * proc, const char * name, int family,
1447 	int type, int protocol)
1448 {
1449 	const char *text = NULL;
1450 
1451 	if (!valuesonly && (type == SOCK_RAW || protocol != 0)) {
1452 		switch (family) {
1453 		case PF_INET:
1454 		case PF_INET6:
1455 			/* TODO: is this all that is used in socket(2)? */
1456 			switch (protocol) {
1457 			TEXT(IPPROTO_IP);
1458 			TEXT(IPPROTO_ICMP);
1459 			TEXT(IPPROTO_IGMP);
1460 			TEXT(IPPROTO_TCP);
1461 			TEXT(IPPROTO_UDP);
1462 			TEXT(IPPROTO_ICMPV6);
1463 			TEXT(IPPROTO_RAW);
1464 			}
1465 			break;
1466 #if 0 /* not yet */
1467 		case PF_BLUETOOTH:
1468 			switch (protocol) {
1469 			TEXT(BTPROTO_HCI);
1470 			TEXT(BTPROTO_L2CAP);
1471 			TEXT(BTPROTO_RFCOMM);
1472 			TEXT(BTPROTO_SCO);
1473 			}
1474 			break;
1475 #endif
1476 		}
1477 	}
1478 
1479 	if (text != NULL)
1480 		put_field(proc, name, text);
1481 	else
1482 		put_value(proc, name, "%d", protocol);
1483 }
1484 
1485 static int
1486 vfs_socket_out(struct trace_proc * proc, const message * m_out)
1487 {
1488 
1489 	put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain);
1490 	put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type);
1491 	put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain,
1492 	    m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK,
1493 	    m_out->m_lc_vfs_socket.protocol);
1494 
1495 	return CT_DONE;
1496 }
1497 
1498 static int
1499 vfs_socketpair_out(struct trace_proc * proc, const message * m_out)
1500 {
1501 
1502 	put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain);
1503 	put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type);
1504 	put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain,
1505 	    m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK,
1506 	    m_out->m_lc_vfs_socket.protocol);
1507 
1508 	return CT_NOTDONE;
1509 }
1510 
1511 static void
1512 vfs_socketpair_in(struct trace_proc * proc, const message * m_out,
1513 	const message * m_in, int failed)
1514 {
1515 
1516 	if (!failed) {
1517 		put_open(proc, "fd", PF_NONAME, "[", ", ");
1518 		put_fd(proc, "fd0", m_in->m_vfs_lc_fdpair.fd0);
1519 		put_fd(proc, "fd1", m_in->m_vfs_lc_fdpair.fd1);
1520 		put_close(proc, "]");
1521 	} else
1522 		put_field(proc, "fd", "&..");
1523 	put_equals(proc);
1524 	put_result(proc);
1525 }
1526 
1527 void
1528 put_in_addr(struct trace_proc * proc, const char * name, struct in_addr in)
1529 {
1530 
1531 	if (!valuesonly) {
1532 		/* Is this an acceptable encapsulation? */
1533 		put_value(proc, name, "[%s]", inet_ntoa(in));
1534 	} else
1535 		put_value(proc, name, "0x%08x", ntohl(in.s_addr));
1536 }
1537 
1538 static void
1539 put_in6_addr(struct trace_proc * proc, const char * name, struct in6_addr * in)
1540 {
1541 	char buf[INET6_ADDRSTRLEN];
1542 	const char *ptr;
1543 	unsigned int i, n;
1544 
1545 	if (!valuesonly &&
1546 	    (ptr = inet_ntop(AF_INET6, in, buf, sizeof(buf))) != NULL) {
1547 		put_value(proc, name, "[%s]", ptr);
1548 	} else {
1549 		for (i = n = 0; i < 16; i++)
1550 			n += snprintf(buf + n, sizeof(buf) - n, "%02x",
1551 			    ((unsigned char *)in)[i]);
1552 		put_value(proc, name, "0x%s", buf);
1553 	}
1554 }
1555 
1556 static void
1557 put_struct_sockaddr(struct trace_proc * proc, const char * name, int flags,
1558 	vir_bytes addr, socklen_t addr_len)
1559 {
1560 	char buf[UCHAR_MAX + 1];
1561 	uint8_t len;
1562 	sa_family_t family;
1563 	struct sockaddr sa;
1564 	struct sockaddr_in sin;
1565 	struct sockaddr_in6 sin6;
1566 	int all, off, left;
1567 
1568 	/*
1569 	 * For UNIX domain sockets, make sure there's always room to add a
1570 	 * trailing NULL byte, because UDS paths are not necessarily null
1571 	 * terminated.
1572 	 */
1573 	if (addr_len < offsetof(struct sockaddr, sa_data) ||
1574 	    addr_len >= sizeof(buf)) {
1575 		put_ptr(proc, name, addr);
1576 
1577 		return;
1578 	}
1579 
1580 	if (!put_open_struct(proc, name, flags, addr, buf, addr_len))
1581 		return;
1582 
1583 	memcpy(&sa, buf, sizeof(sa));
1584 	len = sa.sa_len;
1585 	family = sa.sa_family;
1586 	all = (verbose > 1);
1587 
1588 	switch (family) {
1589 	case AF_LOCAL:
1590 		if (verbose > 1)
1591 			put_value(proc, "sun_len", "%u", len);
1592 		if (verbose > 0)
1593 			put_socket_family(proc, "sun_family", family);
1594 		off = (int)offsetof(struct sockaddr_un, sun_path);
1595 		left = addr_len - off;
1596 		if (left > 0) {
1597 			buf[addr_len] = 0; /* force null termination */
1598 			put_buf(proc, "sun_path", PF_LOCADDR | PF_PATH,
1599 			    (vir_bytes)&buf[off],
1600 			    left + 1 /* include null byte */);
1601 		}
1602 		break;
1603 	case AF_INET:
1604 		if (verbose > 1)
1605 			put_value(proc, "sin_len", "%u", len);
1606 		if (verbose > 0)
1607 			put_socket_family(proc, "sin_family", family);
1608 		if (addr_len == sizeof(sin)) {
1609 			memcpy(&sin, buf, sizeof(sin));
1610 			put_value(proc, "sin_port", "%u", ntohs(sin.sin_port));
1611 			put_in_addr(proc, "sin_addr", sin.sin_addr);
1612 		} else
1613 			all = FALSE;
1614 		break;
1615 	case AF_INET6:
1616 		if (verbose > 1)
1617 			put_value(proc, "sin6_len", "%u", len);
1618 		if (verbose > 0)
1619 			put_socket_family(proc, "sin6_family", family);
1620 		if (addr_len == sizeof(sin6)) {
1621 			memcpy(&sin6, buf, sizeof(sin6));
1622 			put_value(proc, "sin6_port", "%u",
1623 			    ntohs(sin6.sin6_port));
1624 			if (verbose > 1)
1625 				put_value(proc, "sin6_flowinfo", "%"PRIu32,
1626 				    sin6.sin6_flowinfo);
1627 			put_in6_addr(proc, "sin6_addr", &sin6.sin6_addr);
1628 			if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
1629 			    IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
1630 			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) ||
1631 			    verbose > 0)
1632 				put_value(proc, "sin6_scope_id", "%"PRIu32,
1633 				    sin6.sin6_scope_id);
1634 		} else
1635 			all = FALSE;
1636 		break;
1637 	/* TODO: support for other address families */
1638 	default:
1639 		if (verbose > 1)
1640 			put_value(proc, "sa_len", "%u", len);
1641 		put_socket_family(proc, "sa_family", family);
1642 		all = (verbose > 1 && family == AF_UNSPEC);
1643 	}
1644 
1645 	put_close_struct(proc, all);
1646 }
1647 
1648 /* This function is shared between bind and connect. */
1649 static int
1650 vfs_bind_out(struct trace_proc * proc, const message * m_out)
1651 {
1652 
1653 	put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
1654 	put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sockaddr.addr,
1655 	    m_out->m_lc_vfs_sockaddr.addr_len);
1656 	put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sockaddr.addr_len);
1657 
1658 	return CT_DONE;
1659 }
1660 
1661 static int
1662 vfs_listen_out(struct trace_proc * proc, const message * m_out)
1663 {
1664 
1665 	put_fd(proc, "fd", m_out->m_lc_vfs_listen.fd);
1666 	put_value(proc, "backlog", "%d", m_out->m_lc_vfs_listen.backlog);
1667 
1668 	return CT_DONE;
1669 }
1670 
1671 static int
1672 vfs_accept_out(struct trace_proc * proc, const message * m_out)
1673 {
1674 
1675 	put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
1676 
1677 	return CT_NOTDONE;
1678 }
1679 
1680 static void
1681 vfs_accept_in(struct trace_proc * proc, const message * m_out,
1682 	const message * m_in, int failed)
1683 {
1684 
1685 	put_struct_sockaddr(proc, "addr", failed,
1686 	    m_out->m_lc_vfs_sockaddr.addr, m_in->m_vfs_lc_socklen.len);
1687 	/*
1688 	 * We print the resulting address length rather than the given buffer
1689 	 * size here, as we do in recvfrom, getsockname, getpeername, and (less
1690 	 * explicitly) recvmsg.  We could also print both, by adding the
1691 	 * resulting length after the call result.
1692 	 */
1693 	if (m_out->m_lc_vfs_sockaddr.addr == 0)
1694 		put_field(proc, "addr_len", "NULL");
1695 	else if (!failed)
1696 		put_value(proc, "addr_len", "{%u}",
1697 		    m_in->m_vfs_lc_socklen.len);
1698 	else
1699 		put_field(proc, "addr_len", "&..");
1700 
1701 	put_equals(proc);
1702 	put_result(proc);
1703 }
1704 
1705 static const struct flags msg_flags[] = {
1706 	FLAG(MSG_OOB),
1707 	FLAG(MSG_PEEK),
1708 	FLAG(MSG_DONTROUTE),
1709 	FLAG(MSG_EOR),
1710 	FLAG(MSG_TRUNC),
1711 	FLAG(MSG_CTRUNC),
1712 	FLAG(MSG_WAITALL),
1713 	FLAG(MSG_DONTWAIT),
1714 	FLAG(MSG_BCAST),
1715 	FLAG(MSG_MCAST),
1716 #ifdef MSG_NOSIGNAL
1717 	FLAG(MSG_NOSIGNAL),
1718 #endif
1719 	FLAG(MSG_CMSG_CLOEXEC),
1720 	FLAG(MSG_NBIO),
1721 	FLAG(MSG_WAITFORONE),
1722 };
1723 
1724 static int
1725 vfs_sendto_out(struct trace_proc * proc, const message * m_out)
1726 {
1727 
1728 	put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd);
1729 	put_buf(proc, "buf", 0, m_out->m_lc_vfs_sendrecv.buf,
1730 	    m_out->m_lc_vfs_readwrite.len);
1731 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len);
1732 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
1733 	    m_out->m_lc_vfs_sendrecv.flags);
1734 	put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sendrecv.addr,
1735 	    m_out->m_lc_vfs_sendrecv.addr_len);
1736 	put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sendrecv.addr_len);
1737 
1738 	return CT_DONE;
1739 }
1740 
1741 static void
1742 put_struct_iovec(struct trace_proc * proc, const char * name, int flags,
1743 	vir_bytes addr, int len, ssize_t bmax)
1744 {
1745 	struct iovec iov;
1746 	size_t bytes;
1747 	int i, imax;
1748 
1749 	/*
1750 	 * For simplicity and clarity reasons, we currently print the I/O
1751 	 * vector as an array of data elements rather than an array of
1752 	 * structures.  We also copy in each element separately, because as of
1753 	 * writing there is no system support for more than one element anyway.
1754 	 * All of this may be changed later.
1755 	 */
1756 	if ((flags & PF_FAILED) || valuesonly > 1 || addr == 0 || len < 0) {
1757 		put_ptr(proc, name, addr);
1758 
1759 		return;
1760 	}
1761 
1762 	if (len == 0 || bmax == 0) {
1763 		put_field(proc, name, "[]");
1764 
1765 		return;
1766 	}
1767 
1768 	/* As per logic below, 'imax' must be set to a nonzero value here. */
1769 	if (verbose == 0)
1770 		imax = 4;
1771 	else if (verbose == 1)
1772 		imax = 16;
1773 	else
1774 		imax = INT_MAX;
1775 
1776 	for (i = 0; i < len && bmax > 0; i++) {
1777 		if (mem_get_data(proc->pid, addr, &iov, sizeof(iov)) < 0) {
1778 			if (i == 0) {
1779 				put_ptr(proc, name, addr);
1780 
1781 				return;
1782 			}
1783 
1784 			len = imax = 0; /* make put_tail() print an error */
1785 			break;
1786 		}
1787 
1788 		if (i == 0)
1789 			put_open(proc, name, 0, "[", ", ");
1790 
1791 		bytes = MIN(iov.iov_len, (size_t)bmax);
1792 
1793 		if (len < imax)
1794 			put_buf(proc, NULL, 0, (vir_bytes)iov.iov_base, bytes);
1795 
1796 		addr += sizeof(struct iovec);
1797 		bmax -= bytes;
1798 	}
1799 
1800 	if (imax == 0 || imax < len)
1801 		put_tail(proc, len, imax);
1802 	put_close(proc, "]");
1803 }
1804 
1805 static void
1806 put_struct_sockcred(struct trace_proc * proc, const char * name, int flags,
1807 	vir_bytes addr, size_t left)
1808 {
1809 	struct sockcred sc;
1810 
1811 	if (!put_open_struct(proc, name, flags, addr, &sc, sizeof(sc)))
1812 		return;
1813 
1814 	put_value(proc, "sc_uid", "%u", sc.sc_uid);
1815 	if (verbose > 0)
1816 		put_value(proc, "sc_euid", "%u", sc.sc_euid);
1817 	put_value(proc, "sc_gid", "%u", sc.sc_gid);
1818 	if (verbose > 0) {
1819 		put_value(proc, "sc_egid", "%u", sc.sc_egid);
1820 		if (verbose > 1)
1821 			put_value(proc, "sc_ngroups", "%d", sc.sc_ngroups);
1822 		if (left >= sizeof(sc.sc_groups[0]) * (sc.sc_ngroups - 1)) {
1823 			put_groups(proc, "sc_groups", flags,
1824 			    addr + offsetof(struct sockcred, sc_groups),
1825 			    sc.sc_ngroups);
1826 		} else
1827 			put_field(proc, "sc_groups", "..");
1828 	}
1829 
1830 	put_close_struct(proc, verbose > 1);
1831 }
1832 
1833 static void
1834 put_socket_level(struct trace_proc * proc, const char * name, int level)
1835 {
1836 
1837 	/*
1838 	 * Unfortunately, the level is a domain-specific protocol number.  That
1839 	 * means that without knowing how the socket was created, we cannot
1840 	 * tell what it means.  The only thing we can print is SOL_SOCKET,
1841 	 * which is the same across all domains.
1842 	 */
1843 	if (!valuesonly && level == SOL_SOCKET)
1844 		put_field(proc, name, "SOL_SOCKET");
1845 	else
1846 		put_value(proc, name, "%d", level);
1847 }
1848 
1849 void
1850 put_cmsg_type(struct trace_proc * proc, const char * name, int type)
1851 {
1852 	const char *text = NULL;
1853 
1854 	if (!valuesonly) {
1855 		switch (type) {
1856 		TEXT(SCM_RIGHTS);
1857 		TEXT(SCM_CREDS);
1858 		TEXT(SCM_TIMESTAMP);
1859 		}
1860 	}
1861 
1862 	if (text != NULL)
1863 		put_field(proc, name, text);
1864 	else
1865 		put_value(proc, name, "%d", type);
1866 }
1867 
1868 static void
1869 put_cmsg_rights(struct trace_proc * proc, const char * name, char * buf,
1870 	size_t size, char * cptr, size_t chunk, vir_bytes addr, size_t len)
1871 {
1872 	unsigned int i, nfds;
1873 	int *ptr;
1874 
1875 	put_open(proc, name, PF_NONAME, "[", ", ");
1876 
1877 	/*
1878 	 * Since file descriptors are important, we print them all, regardless
1879 	 * of the current verbosity level.  Start with the file descriptors
1880 	 * that are already copied into the local buffer.
1881 	 */
1882 	ptr = (int *)cptr;
1883 	chunk = MIN(chunk, len);
1884 
1885 	nfds = chunk / sizeof(int);
1886 	for (i = 0; i < nfds; i++)
1887 		put_fd(proc, NULL, ptr[i]);
1888 
1889 	/* Then do the remaining file descriptors, in chunks. */
1890 	size -= size % sizeof(int);
1891 
1892 	for (len -= chunk; len >= sizeof(int); len -= chunk) {
1893 		chunk = MIN(len, size);
1894 
1895 		if (mem_get_data(proc->pid, addr, buf, chunk) < 0) {
1896 			put_field(proc, NULL, "..");
1897 
1898 			break;
1899 		}
1900 
1901 		ptr = (int *)buf;
1902 		nfds = chunk / sizeof(int);
1903 		for (i = 0; i < nfds; i++)
1904 			put_fd(proc, NULL, ptr[i]);
1905 
1906 		addr += chunk;
1907 	}
1908 
1909 	put_close(proc, "]");
1910 }
1911 
1912 static void
1913 put_cmsg(struct trace_proc * proc, const char * name, vir_bytes addr,
1914 	size_t len)
1915 {
1916 	struct cmsghdr cmsg;
1917 	char buf[CMSG_SPACE(sizeof(struct sockcred))];
1918 	size_t off, chunk, datalen;
1919 
1920 	if (valuesonly > 1 || addr == 0 || len < CMSG_LEN(0)) {
1921 		put_ptr(proc, name, addr);
1922 
1923 		return;
1924 	}
1925 
1926 	for (off = 0; off < len; off += CMSG_SPACE(datalen)) {
1927 		chunk = MIN(len - off, sizeof(buf));
1928 
1929 		if (chunk < CMSG_LEN(0))
1930 			break;
1931 
1932 		if (mem_get_data(proc->pid, addr + off, buf, chunk) < 0) {
1933 			if (off == 0) {
1934 				put_ptr(proc, name, addr);
1935 
1936 				return;
1937 			}
1938 			break;
1939 		}
1940 
1941 		if (off == 0)
1942 			put_open(proc, name, 0, "[", ", ");
1943 
1944 		memcpy(&cmsg, buf, sizeof(cmsg));
1945 
1946 		put_open(proc, NULL, 0, "{", ", ");
1947 		if (verbose > 0)
1948 			put_value(proc, "cmsg_len", "%u", cmsg.cmsg_len);
1949 		put_socket_level(proc, "cmsg_level", cmsg.cmsg_level);
1950 		if (cmsg.cmsg_level == SOL_SOCKET)
1951 			put_cmsg_type(proc, "cmsg_type", cmsg.cmsg_type);
1952 		else
1953 			put_value(proc, "cmsg_type", "%d", cmsg.cmsg_type);
1954 
1955 		if (cmsg.cmsg_len < CMSG_LEN(0) || off + cmsg.cmsg_len > len) {
1956 			put_tail(proc, 0, 0);
1957 			put_close(proc, "}");
1958 			break;
1959 		}
1960 
1961 		datalen = cmsg.cmsg_len - CMSG_LEN(0);
1962 
1963 		if (cmsg.cmsg_level == SOL_SOCKET &&
1964 		    cmsg.cmsg_type == SCM_RIGHTS) {
1965 			put_cmsg_rights(proc, "cmsg_data", buf, sizeof(buf),
1966 			    &buf[CMSG_LEN(0)], chunk - CMSG_LEN(0),
1967 			    addr + off + chunk, datalen);
1968 		} else if (cmsg.cmsg_level == SOL_SOCKET &&
1969 		    cmsg.cmsg_type == SCM_CREDS &&
1970 		    datalen >= sizeof(struct sockcred) &&
1971 		    chunk >= CMSG_LEN(datalen)) {
1972 			put_struct_sockcred(proc, "cmsg_data", PF_LOCADDR,
1973 			    (vir_bytes)&buf[CMSG_LEN(0)],
1974 			    datalen - sizeof(struct sockcred));
1975 		} else if (datalen > 0)
1976 			put_field(proc, "cmsg_data", "..");
1977 
1978 		if (verbose == 0)
1979 			put_field(proc, NULL, "..");
1980 		put_close(proc, "}");
1981 	}
1982 
1983 	if (off < len)
1984 		put_field(proc, NULL, "..");
1985 	put_close(proc, "]");
1986 }
1987 
1988 static void
1989 put_struct_msghdr(struct trace_proc * proc, const char * name, int flags,
1990 	vir_bytes addr, ssize_t max)
1991 {
1992 	struct msghdr msg;
1993 	int all;
1994 
1995 	if (!put_open_struct(proc, name, flags, addr, &msg, sizeof(msg)))
1996 		return;
1997 
1998 	all = TRUE;
1999 
2000 	if (msg.msg_name != NULL || verbose > 1) {
2001 		put_struct_sockaddr(proc, "msg_name", 0,
2002 		    (vir_bytes)msg.msg_name, msg.msg_namelen);
2003 		if (verbose > 0)
2004 			put_value(proc, "msg_namelen", "%u", msg.msg_namelen);
2005 		else
2006 			all = FALSE;
2007 	} else
2008 		all = FALSE;
2009 
2010 	put_struct_iovec(proc, "msg_iov", 0, (vir_bytes)msg.msg_iov,
2011 	    msg.msg_iovlen, max);
2012 	if (verbose > 0)
2013 		put_value(proc, "msg_iovlen", "%d", msg.msg_iovlen);
2014 	else
2015 		all = FALSE;
2016 
2017 	if (msg.msg_control != NULL || verbose > 1) {
2018 		put_cmsg(proc, "msg_control", (vir_bytes)msg.msg_control,
2019 		    msg.msg_controllen);
2020 
2021 		if (verbose > 0)
2022 			put_value(proc, "msg_controllen", "%u",
2023 			    msg.msg_controllen);
2024 		else
2025 			all = FALSE;
2026 	} else
2027 		all = FALSE;
2028 
2029 	/* When receiving, print the flags field as well. */
2030 	if (flags & PF_ALT)
2031 		put_flags(proc, "msg_flags", msg_flags, COUNT(msg_flags),
2032 		    "0x%x", msg.msg_flags);
2033 
2034 	put_close_struct(proc, all);
2035 }
2036 
2037 static int
2038 vfs_sendmsg_out(struct trace_proc * proc, const message * m_out)
2039 {
2040 
2041 	put_fd(proc, "fd", m_out->m_lc_vfs_sockmsg.fd);
2042 	put_struct_msghdr(proc, "msg", 0, m_out->m_lc_vfs_sockmsg.msgbuf,
2043 	    SSIZE_MAX);
2044 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
2045 	    m_out->m_lc_vfs_sockmsg.flags);
2046 
2047 	return CT_DONE;
2048 }
2049 
2050 static int
2051 vfs_recvfrom_out(struct trace_proc * proc, const message * m_out)
2052 {
2053 
2054 	put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd);
2055 
2056 	return CT_NOTDONE;
2057 }
2058 
2059 static void
2060 vfs_recvfrom_in(struct trace_proc * proc, const message * m_out,
2061 	const message * m_in, int failed)
2062 {
2063 
2064 	put_buf(proc, "buf", failed, m_out->m_lc_vfs_sendrecv.buf,
2065 	    m_in->m_type);
2066 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len);
2067 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
2068 	    m_out->m_lc_vfs_sendrecv.flags);
2069 	put_struct_sockaddr(proc, "addr", failed,
2070 	    m_out->m_lc_vfs_sendrecv.addr, m_in->m_vfs_lc_socklen.len);
2071 	if (m_out->m_lc_vfs_sendrecv.addr == 0)
2072 		put_field(proc, "addr_len", "NULL");
2073 	else if (!failed)
2074 		put_value(proc, "addr_len", "{%u}",
2075 		    m_in->m_vfs_lc_socklen.len);
2076 	else
2077 		put_field(proc, "addr_len", "&..");
2078 
2079 	put_equals(proc);
2080 	put_result(proc);
2081 }
2082 
2083 static int
2084 vfs_recvmsg_out(struct trace_proc * proc, const message * m_out)
2085 {
2086 
2087 	put_fd(proc, "fd", m_out->m_lc_vfs_sockmsg.fd);
2088 
2089 	return CT_NOTDONE;
2090 }
2091 
2092 static void
2093 vfs_recvmsg_in(struct trace_proc * proc, const message * m_out,
2094 	const message * m_in, int failed)
2095 {
2096 
2097 	/*
2098 	 * We choose to print only the resulting structure in this case.  Doing
2099 	 * so is easier and less messy than printing both the original and the
2100 	 * result for the fields that are updated by the system (msg_namelen
2101 	 * and msg_controllen); also, this approach is stateless.  Admittedly
2102 	 * it is not entirely consistent with many other parts of the trace
2103 	 * output, though.
2104 	 */
2105 	put_struct_msghdr(proc, "msg", PF_ALT | failed,
2106 	    m_out->m_lc_vfs_sockmsg.msgbuf, m_in->m_type);
2107 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
2108 	    m_out->m_lc_vfs_sockmsg.flags);
2109 
2110 	put_equals(proc);
2111 	put_result(proc);
2112 }
2113 
2114 static void
2115 put_sockopt_name(struct trace_proc * proc, const char * name, int level,
2116 	int optname)
2117 {
2118 	const char *text = NULL;
2119 
2120 	/*
2121 	 * The only level for which we can know names is SOL_SOCKET.  See also
2122 	 * put_socket_level().  Of course we could guess, but then we need a
2123 	 * proper guessing system, which should probably also take into account
2124 	 * the [gs]etsockopt option length.  TODO.
2125 	 */
2126 	if (!valuesonly && level == SOL_SOCKET) {
2127 		switch (optname) {
2128 		TEXT(SO_DEBUG);
2129 		TEXT(SO_ACCEPTCONN);
2130 		TEXT(SO_REUSEADDR);
2131 		TEXT(SO_KEEPALIVE);
2132 		TEXT(SO_DONTROUTE);
2133 		TEXT(SO_BROADCAST);
2134 		TEXT(SO_USELOOPBACK);
2135 		TEXT(SO_LINGER);
2136 		TEXT(SO_OOBINLINE);
2137 		TEXT(SO_REUSEPORT);
2138 		TEXT(SO_NOSIGPIPE);
2139 		TEXT(SO_TIMESTAMP);
2140 		TEXT(SO_SNDBUF);
2141 		TEXT(SO_RCVBUF);
2142 		TEXT(SO_SNDLOWAT);
2143 		TEXT(SO_RCVLOWAT);
2144 		TEXT(SO_ERROR);
2145 		TEXT(SO_TYPE);
2146 		TEXT(SO_OVERFLOWED);
2147 		TEXT(SO_NOHEADER);
2148 		TEXT(SO_SNDTIMEO);
2149 		TEXT(SO_RCVTIMEO);
2150 		}
2151 	}
2152 
2153 	if (text != NULL)
2154 		put_field(proc, name, text);
2155 	else
2156 		put_value(proc, name, "0x%x", optname);
2157 }
2158 
2159 static void
2160 put_sockopt_data(struct trace_proc * proc, const char * name, int flags,
2161 	int level, int optname, vir_bytes addr, socklen_t len)
2162 {
2163 	const char *text;
2164 	int i;
2165 	struct linger l;
2166 	struct timeval tv;
2167 	void *ptr;
2168 	size_t size;
2169 
2170 	/* See above regarding ambiguity for levels other than SOL_SOCKET. */
2171 	if ((flags & PF_FAILED) || valuesonly > 1 || len == 0 ||
2172 	    level != SOL_SOCKET) {
2173 		put_ptr(proc, name, addr);
2174 
2175 		return;
2176 	}
2177 
2178 	/* Determine how much data to get, and where to put it. */
2179 	switch (optname) {
2180 	case SO_DEBUG:
2181 	case SO_ACCEPTCONN:
2182 	case SO_REUSEADDR:
2183 	case SO_KEEPALIVE:
2184 	case SO_DONTROUTE:
2185 	case SO_BROADCAST:
2186 	case SO_USELOOPBACK:
2187 	case SO_OOBINLINE:
2188 	case SO_REUSEPORT:
2189 	case SO_NOSIGPIPE:
2190 	case SO_TIMESTAMP:
2191 	case SO_SNDBUF:
2192 	case SO_RCVBUF:
2193 	case SO_SNDLOWAT:
2194 	case SO_RCVLOWAT:
2195 	case SO_ERROR:
2196 	case SO_TYPE:
2197 	case SO_OVERFLOWED:
2198 	case SO_NOHEADER:
2199 		ptr = &i;
2200 		size = sizeof(i);
2201 		break;
2202 	case SO_LINGER:
2203 		ptr = &l;
2204 		size = sizeof(l);
2205 		break;
2206 	case SO_SNDTIMEO:
2207 	case SO_RCVTIMEO:
2208 		ptr = &tv;
2209 		size = sizeof(tv);
2210 		break;
2211 	default:
2212 		put_ptr(proc, name, addr);
2213 		return;
2214 	}
2215 
2216 	/* Get the data.  Do not bother with truncated values. */
2217 	if (len < size || mem_get_data(proc->pid, addr, ptr, size) < 0) {
2218 		put_ptr(proc, name, addr);
2219 
2220 		return;
2221 	}
2222 
2223 	/* Print the data according to the option name. */
2224 	switch (optname) {
2225 	case SO_LINGER:
2226 		/* This isn't going to appear anywhere else; do it inline. */
2227 		put_open(proc, name, 0, "{", ", ");
2228 		put_value(proc, "l_onoff", "%d", l.l_onoff);
2229 		put_value(proc, "l_linger", "%d", l.l_linger);
2230 		put_close(proc, "}");
2231 		break;
2232 	case SO_ERROR:
2233 		put_open(proc, name, 0, "{", ", ");
2234 		if (!valuesonly && (text = get_error_name(i)) != NULL)
2235 			put_field(proc, NULL, text);
2236 		else
2237 			put_value(proc, NULL, "%d", i);
2238 		put_close(proc, "}");
2239 		break;
2240 	case SO_TYPE:
2241 		put_open(proc, name, 0, "{", ", ");
2242 		put_socket_type(proc, NULL, i);
2243 		put_close(proc, "}");
2244 		break;
2245 	case SO_SNDTIMEO:
2246 	case SO_RCVTIMEO:
2247 		put_struct_timeval(proc, name, PF_LOCADDR, (vir_bytes)&tv);
2248 		break;
2249 	default:
2250 		/* All other options are integer values. */
2251 		put_value(proc, name, "{%d}", i);
2252 	}
2253 }
2254 
2255 static int
2256 vfs_setsockopt_out(struct trace_proc * proc, const message * m_out)
2257 {
2258 	int level, name;
2259 
2260 	level = m_out->m_lc_vfs_sockopt.level;
2261 	name = m_out->m_lc_vfs_sockopt.name;
2262 
2263 	put_fd(proc, "fd", m_out->m_lc_vfs_sockopt.fd);
2264 	put_socket_level(proc, "level", level);
2265 	put_sockopt_name(proc, "name", level, name);
2266 	put_sockopt_data(proc, "buf", 0, level, name,
2267 	    m_out->m_lc_vfs_sockopt.buf, m_out->m_lc_vfs_sockopt.len);
2268 	put_value(proc, "len", "%u", m_out->m_lc_vfs_sockopt.len);
2269 
2270 	return CT_DONE;
2271 }
2272 
2273 static int
2274 vfs_getsockopt_out(struct trace_proc * proc, const message * m_out)
2275 {
2276 	int level;
2277 
2278 	level = m_out->m_lc_vfs_sockopt.level;
2279 
2280 	put_fd(proc, "fd", m_out->m_lc_vfs_sockopt.fd);
2281 	put_socket_level(proc, "level", level);
2282 	put_sockopt_name(proc, "name", level, m_out->m_lc_vfs_sockopt.name);
2283 
2284 	return CT_NOTDONE;
2285 }
2286 
2287 static void
2288 vfs_getsockopt_in(struct trace_proc * proc, const message * m_out,
2289 	const message * m_in, int failed)
2290 {
2291 
2292 	put_sockopt_data(proc, "buf", failed, m_out->m_lc_vfs_sockopt.level,
2293 	    m_out->m_lc_vfs_sockopt.name, m_out->m_lc_vfs_sockopt.buf,
2294 	    m_in->m_vfs_lc_socklen.len);
2295 	/*
2296 	 * For the length, we follow the same scheme as for addr_len pointers
2297 	 * in accept() et al., in that we print the result only.  We need not
2298 	 * take into account that the given buffer is NULL as it must not be.
2299 	 */
2300 	if (!failed)
2301 		put_value(proc, "len", "%u", m_out->m_lc_vfs_sockopt.len);
2302 	else
2303 		put_field(proc, "len", "&..");
2304 
2305 	put_equals(proc);
2306 	put_result(proc);
2307 }
2308 
2309 /* This function is shared between getsockname and getpeername. */
2310 static int
2311 vfs_getsockname_out(struct trace_proc * proc, const message * m_out)
2312 {
2313 
2314 	put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
2315 
2316 	return CT_NOTDONE;
2317 }
2318 
2319 static void
2320 vfs_getsockname_in(struct trace_proc * proc, const message * m_out,
2321 	const message * m_in, int failed)
2322 {
2323 
2324 	put_struct_sockaddr(proc, "addr", failed,
2325 	    m_out->m_lc_vfs_sockaddr.addr, m_in->m_vfs_lc_socklen.len);
2326 	if (m_out->m_lc_vfs_sockaddr.addr == 0)
2327 		put_field(proc, "addr_len", "NULL");
2328 	else if (!failed)
2329 		put_value(proc, "addr_len", "{%u}",
2330 		    m_in->m_vfs_lc_socklen.len);
2331 	else
2332 		put_field(proc, "addr_len", "&..");
2333 
2334 	put_equals(proc);
2335 	put_result(proc);
2336 }
2337 
2338 void
2339 put_shutdown_how(struct trace_proc * proc, const char * name, int how)
2340 {
2341 	const char *text = NULL;
2342 
2343 	if (!valuesonly) {
2344 		switch (how) {
2345 		TEXT(SHUT_RD);
2346 		TEXT(SHUT_WR);
2347 		TEXT(SHUT_RDWR);
2348 		}
2349 	}
2350 
2351 	if (text != NULL)
2352 		put_field(proc, name, text);
2353 	else
2354 		put_value(proc, name, "%d", how);
2355 }
2356 
2357 static int
2358 vfs_shutdown_out(struct trace_proc * proc, const message * m_out)
2359 {
2360 
2361 	put_fd(proc, "fd", m_out->m_lc_vfs_shutdown.fd);
2362 	put_shutdown_how(proc, "how", m_out->m_lc_vfs_shutdown.how);
2363 
2364 	return CT_DONE;
2365 }
2366 
2367 #define VFS_CALL(c) [((VFS_ ## c) - VFS_BASE)]
2368 
2369 static const struct call_handler vfs_map[] = {
2370 	VFS_CALL(READ) = HANDLER("read", vfs_read_out, vfs_read_in),
2371 	VFS_CALL(WRITE) = HANDLER("write", vfs_write_out, default_in),
2372 	VFS_CALL(LSEEK) = HANDLER("lseek", vfs_lseek_out, vfs_lseek_in),
2373 	VFS_CALL(OPEN) = HANDLER("open", vfs_open_out, vfs_open_in),
2374 	VFS_CALL(CREAT) = HANDLER("open", vfs_creat_out, vfs_open_in),
2375 	VFS_CALL(CLOSE) = HANDLER("close", vfs_close_out, default_in),
2376 	VFS_CALL(LINK) = HANDLER("link", vfs_link_out, default_in),
2377 	VFS_CALL(UNLINK) = HANDLER("unlink", vfs_path_out, default_in),
2378 	VFS_CALL(CHDIR) = HANDLER("chdir", vfs_path_out, default_in),
2379 	VFS_CALL(MKDIR) = HANDLER("mkdir", vfs_path_mode_out, default_in),
2380 	VFS_CALL(MKNOD) = HANDLER("mknod", vfs_mknod_out, default_in),
2381 	VFS_CALL(CHMOD) = HANDLER("chmod", vfs_path_mode_out, default_in),
2382 	VFS_CALL(CHOWN) = HANDLER("chown", vfs_chown_out, default_in),
2383 	VFS_CALL(MOUNT) = HANDLER("mount", vfs_mount_out, default_in),
2384 	VFS_CALL(UMOUNT) = HANDLER("umount", vfs_umount_out, vfs_umount_in),
2385 	VFS_CALL(ACCESS) = HANDLER("access", vfs_access_out, default_in),
2386 	VFS_CALL(SYNC) = HANDLER("sync", default_out, default_in),
2387 	VFS_CALL(RENAME) = HANDLER("rename", vfs_link_out, default_in),
2388 	VFS_CALL(RMDIR) = HANDLER("rmdir", vfs_path_out, default_in),
2389 	VFS_CALL(SYMLINK) = HANDLER("symlink", vfs_link_out, default_in),
2390 	VFS_CALL(READLINK) = HANDLER("readlink", vfs_readlink_out,
2391 	    vfs_readlink_in),
2392 	VFS_CALL(STAT) = HANDLER("stat", vfs_stat_out, vfs_stat_in),
2393 	VFS_CALL(FSTAT) = HANDLER("fstat", vfs_fstat_out, vfs_fstat_in),
2394 	VFS_CALL(LSTAT) = HANDLER("lstat", vfs_stat_out, vfs_stat_in),
2395 	VFS_CALL(IOCTL) = HANDLER("ioctl", vfs_ioctl_out, vfs_ioctl_in),
2396 	VFS_CALL(FCNTL) = HANDLER("fcntl", vfs_fcntl_out, vfs_fcntl_in),
2397 	VFS_CALL(PIPE2) = HANDLER("pipe2", vfs_pipe2_out, vfs_pipe2_in),
2398 	VFS_CALL(UMASK) = HANDLER("umask", vfs_umask_out, vfs_umask_in),
2399 	VFS_CALL(CHROOT) = HANDLER("chroot", vfs_path_out, default_in),
2400 	VFS_CALL(GETDENTS) = HANDLER("getdents", vfs_getdents_out,
2401 	    vfs_getdents_in),
2402 	VFS_CALL(SELECT) = HANDLER("select", vfs_select_out, vfs_select_in),
2403 	VFS_CALL(FCHDIR) = HANDLER("fchdir", vfs_fchdir_out, default_in),
2404 	VFS_CALL(FSYNC) = HANDLER("fsync", vfs_fsync_out, default_in),
2405 	VFS_CALL(TRUNCATE) = HANDLER("truncate", vfs_truncate_out, default_in),
2406 	VFS_CALL(FTRUNCATE) = HANDLER("ftruncate", vfs_ftruncate_out,
2407 	    default_in),
2408 	VFS_CALL(FCHMOD) = HANDLER("fchmod", vfs_fchmod_out, default_in),
2409 	VFS_CALL(FCHOWN) = HANDLER("fchown", vfs_fchown_out, default_in),
2410 	VFS_CALL(UTIMENS) = HANDLER_NAME(vfs_utimens_name, vfs_utimens_out,
2411 	    default_in),
2412 	VFS_CALL(GETVFSSTAT) = HANDLER("getvfsstat", vfs_getvfsstat_out,
2413 	    vfs_getvfsstat_in),
2414 	VFS_CALL(STATVFS1) = HANDLER("statvfs1", vfs_statvfs1_out,
2415 	    vfs_statvfs1_in),
2416 	VFS_CALL(FSTATVFS1) = HANDLER("fstatvfs1", vfs_fstatvfs1_out,
2417 	    vfs_statvfs1_in),
2418 	VFS_CALL(SVRCTL) = HANDLER("vfs_svrctl", vfs_svrctl_out,
2419 	    vfs_svrctl_in),
2420 	VFS_CALL(GCOV_FLUSH) = HANDLER("gcov_flush", vfs_gcov_flush_out,
2421 	    default_in),
2422 	VFS_CALL(SOCKET) = HANDLER("socket", vfs_socket_out, default_in),
2423 	VFS_CALL(SOCKETPAIR) = HANDLER("socketpair", vfs_socketpair_out,
2424 	    vfs_socketpair_in),
2425 	VFS_CALL(BIND) = HANDLER("bind", vfs_bind_out, default_in),
2426 	VFS_CALL(CONNECT) = HANDLER("connect", vfs_bind_out, default_in),
2427 	VFS_CALL(LISTEN) = HANDLER("listen", vfs_listen_out, default_in),
2428 	VFS_CALL(ACCEPT) = HANDLER("accept", vfs_accept_out, vfs_accept_in),
2429 	VFS_CALL(SENDTO) = HANDLER("sendto", vfs_sendto_out, default_in),
2430 	VFS_CALL(SENDMSG) = HANDLER("sendmsg", vfs_sendmsg_out, default_in),
2431 	VFS_CALL(RECVFROM) = HANDLER("recvfrom", vfs_recvfrom_out,
2432 	    vfs_recvfrom_in),
2433 	VFS_CALL(RECVMSG) = HANDLER("recvmsg", vfs_recvmsg_out,
2434 	    vfs_recvmsg_in),
2435 	VFS_CALL(SETSOCKOPT) = HANDLER("setsockopt", vfs_setsockopt_out,
2436 	    default_in),
2437 	VFS_CALL(GETSOCKOPT) = HANDLER("getsockopt", vfs_getsockopt_out,
2438 	    vfs_getsockopt_in),
2439 	VFS_CALL(GETSOCKNAME) = HANDLER("getsockname", vfs_getsockname_out,
2440 	    vfs_getsockname_in),
2441 	VFS_CALL(GETPEERNAME) = HANDLER("getpeername", vfs_getsockname_out,
2442 	    vfs_getsockname_in),
2443 	VFS_CALL(SHUTDOWN) = HANDLER("shutdown", vfs_shutdown_out, default_in),
2444 };
2445 
2446 const struct calls vfs_calls = {
2447 	.endpt = VFS_PROC_NR,
2448 	.base = VFS_BASE,
2449 	.map = vfs_map,
2450 	.count = COUNT(vfs_map)
2451 };
2452