xref: /minix/minix/usr.bin/trace/service/vfs.c (revision 27852ebe)
1521fa314SDavid van Moolenbroek 
2521fa314SDavid van Moolenbroek #include "inc.h"
3521fa314SDavid van Moolenbroek 
4521fa314SDavid van Moolenbroek #include <fcntl.h>
5521fa314SDavid van Moolenbroek #include <unistd.h>
6521fa314SDavid van Moolenbroek #include <dirent.h>
7521fa314SDavid van Moolenbroek #include <sys/mount.h>
8521fa314SDavid van Moolenbroek #include <sys/resource.h>
9c38dbb97SDavid van Moolenbroek #include <sys/socket.h>
10c38dbb97SDavid van Moolenbroek #include <sys/un.h>
11c38dbb97SDavid van Moolenbroek #include <netinet/in.h>
12c38dbb97SDavid van Moolenbroek #if 0 /* not yet, header is missing */
13c38dbb97SDavid van Moolenbroek #include <netbt/bluetooth.h>
14c38dbb97SDavid van Moolenbroek #endif
15c38dbb97SDavid van Moolenbroek #include <arpa/inet.h>
16521fa314SDavid van Moolenbroek 
17521fa314SDavid van Moolenbroek /*
18521fa314SDavid van Moolenbroek  * This function should always be used when printing a file descriptor.  It
19521fa314SDavid van Moolenbroek  * currently offers no benefit, but will in the future allow for features such
20521fa314SDavid van Moolenbroek  * as color highlighting and tracking of specific open files (TODO).
21521fa314SDavid van Moolenbroek  */
22521fa314SDavid van Moolenbroek void
put_fd(struct trace_proc * proc,const char * name,int fd)23521fa314SDavid van Moolenbroek put_fd(struct trace_proc * proc, const char * name, int fd)
24521fa314SDavid van Moolenbroek {
25521fa314SDavid van Moolenbroek 
26521fa314SDavid van Moolenbroek 	put_value(proc, name, "%d", fd);
27521fa314SDavid van Moolenbroek }
28521fa314SDavid van Moolenbroek 
29521fa314SDavid van Moolenbroek static int
vfs_read_out(struct trace_proc * proc,const message * m_out)30521fa314SDavid van Moolenbroek vfs_read_out(struct trace_proc * proc, const message * m_out)
31521fa314SDavid van Moolenbroek {
32521fa314SDavid van Moolenbroek 
33521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
34521fa314SDavid van Moolenbroek 
35521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
36521fa314SDavid van Moolenbroek }
37521fa314SDavid van Moolenbroek 
38521fa314SDavid van Moolenbroek static void
vfs_read_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)39521fa314SDavid van Moolenbroek vfs_read_in(struct trace_proc * proc, const message * m_out,
40521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
41521fa314SDavid van Moolenbroek {
42521fa314SDavid van Moolenbroek 
43521fa314SDavid van Moolenbroek 	put_buf(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf,
44521fa314SDavid van Moolenbroek 	    m_in->m_type);
45521fa314SDavid van Moolenbroek 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
46521fa314SDavid van Moolenbroek 	put_equals(proc);
47521fa314SDavid van Moolenbroek 	put_result(proc);
48521fa314SDavid van Moolenbroek }
49521fa314SDavid van Moolenbroek 
50521fa314SDavid van Moolenbroek static int
vfs_write_out(struct trace_proc * proc,const message * m_out)51521fa314SDavid van Moolenbroek vfs_write_out(struct trace_proc * proc, const message * m_out)
52521fa314SDavid van Moolenbroek {
53521fa314SDavid van Moolenbroek 
54521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
55521fa314SDavid van Moolenbroek 	put_buf(proc, "buf", 0, m_out->m_lc_vfs_readwrite.buf,
56521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_readwrite.len);
57521fa314SDavid van Moolenbroek 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
58521fa314SDavid van Moolenbroek 
59521fa314SDavid van Moolenbroek 	return CT_DONE;
60521fa314SDavid van Moolenbroek }
61521fa314SDavid van Moolenbroek 
62521fa314SDavid van Moolenbroek static void
put_lseek_whence(struct trace_proc * proc,const char * name,int whence)63521fa314SDavid van Moolenbroek put_lseek_whence(struct trace_proc * proc, const char * name, int whence)
64521fa314SDavid van Moolenbroek {
65521fa314SDavid van Moolenbroek 	const char *text = NULL;
66521fa314SDavid van Moolenbroek 
67521fa314SDavid van Moolenbroek 	if (!valuesonly) {
68521fa314SDavid van Moolenbroek 		switch (whence) {
69521fa314SDavid van Moolenbroek 		TEXT(SEEK_SET);
70521fa314SDavid van Moolenbroek 		TEXT(SEEK_CUR);
71521fa314SDavid van Moolenbroek 		TEXT(SEEK_END);
72521fa314SDavid van Moolenbroek 		}
73521fa314SDavid van Moolenbroek 	}
74521fa314SDavid van Moolenbroek 
75521fa314SDavid van Moolenbroek 	if (text != NULL)
76521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
77521fa314SDavid van Moolenbroek 	else
78521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", whence);
79521fa314SDavid van Moolenbroek }
80521fa314SDavid van Moolenbroek 
81521fa314SDavid van Moolenbroek static int
vfs_lseek_out(struct trace_proc * proc,const message * m_out)82521fa314SDavid van Moolenbroek vfs_lseek_out(struct trace_proc * proc, const message * m_out)
83521fa314SDavid van Moolenbroek {
84521fa314SDavid van Moolenbroek 
85521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_lseek.fd);
86521fa314SDavid van Moolenbroek 	put_value(proc, "offset", "%"PRId64, m_out->m_lc_vfs_lseek.offset);
87521fa314SDavid van Moolenbroek 	put_lseek_whence(proc, "whence", m_out->m_lc_vfs_lseek.whence);
88521fa314SDavid van Moolenbroek 
89521fa314SDavid van Moolenbroek 	return CT_DONE;
90521fa314SDavid van Moolenbroek }
91521fa314SDavid van Moolenbroek 
92521fa314SDavid van Moolenbroek static void
vfs_lseek_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)93521fa314SDavid van Moolenbroek vfs_lseek_in(struct trace_proc * proc, const message * __unused m_out,
94521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
95521fa314SDavid van Moolenbroek {
96521fa314SDavid van Moolenbroek 
97521fa314SDavid van Moolenbroek 	if (!failed)
98521fa314SDavid van Moolenbroek 		put_value(proc, NULL, "%"PRId64, m_in->m_vfs_lc_lseek.offset);
99521fa314SDavid van Moolenbroek 	else
100521fa314SDavid van Moolenbroek 		put_result(proc);
101521fa314SDavid van Moolenbroek }
102521fa314SDavid van Moolenbroek 
103521fa314SDavid van Moolenbroek static const struct flags open_flags[] = {
104521fa314SDavid van Moolenbroek 	FLAG_MASK(O_ACCMODE, O_RDONLY),
105521fa314SDavid van Moolenbroek 	FLAG_MASK(O_ACCMODE, O_WRONLY),
106521fa314SDavid van Moolenbroek 	FLAG_MASK(O_ACCMODE, O_RDWR),
107521fa314SDavid van Moolenbroek #define ACCMODE_ENTRIES 3	/* the first N entries are for O_ACCMODE */
108521fa314SDavid van Moolenbroek 	FLAG(O_NONBLOCK),
109521fa314SDavid van Moolenbroek 	FLAG(O_APPEND),
110521fa314SDavid van Moolenbroek 	FLAG(O_SHLOCK),
111521fa314SDavid van Moolenbroek 	FLAG(O_EXLOCK),
112521fa314SDavid van Moolenbroek 	FLAG(O_ASYNC),
113521fa314SDavid van Moolenbroek 	FLAG(O_SYNC),
114521fa314SDavid van Moolenbroek 	FLAG(O_NOFOLLOW),
115521fa314SDavid van Moolenbroek 	FLAG(O_CREAT),
116521fa314SDavid van Moolenbroek 	FLAG(O_TRUNC),
117521fa314SDavid van Moolenbroek 	FLAG(O_EXCL),
118521fa314SDavid van Moolenbroek 	FLAG(O_NOCTTY),
119521fa314SDavid van Moolenbroek 	FLAG(O_DSYNC),
120521fa314SDavid van Moolenbroek 	FLAG(O_RSYNC),
121521fa314SDavid van Moolenbroek 	FLAG(O_ALT_IO),
122521fa314SDavid van Moolenbroek 	FLAG(O_DIRECT),
123521fa314SDavid van Moolenbroek 	FLAG(O_DIRECTORY),
124521fa314SDavid van Moolenbroek 	FLAG(O_CLOEXEC),
125521fa314SDavid van Moolenbroek 	FLAG(O_SEARCH),
126521fa314SDavid van Moolenbroek 	FLAG(O_NOSIGPIPE),
127521fa314SDavid van Moolenbroek };
128521fa314SDavid van Moolenbroek 
129521fa314SDavid van Moolenbroek static void
put_open_flags(struct trace_proc * proc,const char * name,int value,int full)130521fa314SDavid van Moolenbroek put_open_flags(struct trace_proc * proc, const char * name, int value,
131521fa314SDavid van Moolenbroek 	int full)
132521fa314SDavid van Moolenbroek {
133521fa314SDavid van Moolenbroek 	const struct flags *fp;
134521fa314SDavid van Moolenbroek 	unsigned int num;
135521fa314SDavid van Moolenbroek 
136521fa314SDavid van Moolenbroek 	fp = open_flags;
137521fa314SDavid van Moolenbroek 	num = COUNT(open_flags);
138521fa314SDavid van Moolenbroek 
139521fa314SDavid van Moolenbroek 	/*
140521fa314SDavid van Moolenbroek 	 * If we're not printing a full open()-style set of flags, but instead
141521fa314SDavid van Moolenbroek 	 * just a loose set of flags, then skip the access mode altogether,
142521fa314SDavid van Moolenbroek 	 * otherwise we'd be printing O_RDONLY when no access mode is given.
143521fa314SDavid van Moolenbroek 	 */
144521fa314SDavid van Moolenbroek 	if (!full) {
145521fa314SDavid van Moolenbroek 		fp += ACCMODE_ENTRIES;
146521fa314SDavid van Moolenbroek 		num -= ACCMODE_ENTRIES;
147521fa314SDavid van Moolenbroek 	}
148521fa314SDavid van Moolenbroek 
149521fa314SDavid van Moolenbroek 	put_flags(proc, name, fp, num, "0x%x", value);
150521fa314SDavid van Moolenbroek }
151521fa314SDavid van Moolenbroek 
152521fa314SDavid van Moolenbroek static const struct flags mode_flags[] = {
153521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFIFO),
154521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFCHR),
155521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFDIR),
156521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFBLK),
157521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFREG),
158521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFLNK),
159521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFSOCK),
160521fa314SDavid van Moolenbroek 	FLAG_MASK(S_IFMT, S_IFWHT),
161521fa314SDavid van Moolenbroek 	FLAG(S_ARCH1),
162521fa314SDavid van Moolenbroek 	FLAG(S_ARCH2),
163521fa314SDavid van Moolenbroek 	FLAG(S_ISUID),
164521fa314SDavid van Moolenbroek 	FLAG(S_ISGID),
165521fa314SDavid van Moolenbroek 	FLAG(S_ISTXT),
166521fa314SDavid van Moolenbroek };
167521fa314SDavid van Moolenbroek 
168521fa314SDavid van Moolenbroek /* Do not use %04o instead of 0%03o; it is octal even if greater than 0777. */
169521fa314SDavid van Moolenbroek #define put_mode(p, n, v) \
170521fa314SDavid van Moolenbroek 	put_flags(p, n, mode_flags, COUNT(mode_flags), "0%03o", v)
171521fa314SDavid van Moolenbroek 
172521fa314SDavid van Moolenbroek static void
put_path(struct trace_proc * proc,const message * m_out)173521fa314SDavid van Moolenbroek put_path(struct trace_proc * proc, const message * m_out)
174521fa314SDavid van Moolenbroek {
175521fa314SDavid van Moolenbroek 	size_t len;
176521fa314SDavid van Moolenbroek 
177521fa314SDavid van Moolenbroek 	if ((len = m_out->m_lc_vfs_path.len) <= M_PATH_STRING_MAX)
178521fa314SDavid van Moolenbroek 		put_buf(proc, "path", PF_LOCADDR | PF_PATH,
179521fa314SDavid van Moolenbroek 		    (vir_bytes)m_out->m_lc_vfs_path.buf, len);
180521fa314SDavid van Moolenbroek 	else
181521fa314SDavid van Moolenbroek 		put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_path.name, len);
182521fa314SDavid van Moolenbroek }
183521fa314SDavid van Moolenbroek 
184521fa314SDavid van Moolenbroek static int
vfs_open_out(struct trace_proc * proc,const message * m_out)185521fa314SDavid van Moolenbroek vfs_open_out(struct trace_proc * proc, const message * m_out)
186521fa314SDavid van Moolenbroek {
187521fa314SDavid van Moolenbroek 
188521fa314SDavid van Moolenbroek 	put_path(proc, m_out);
189521fa314SDavid van Moolenbroek 	put_open_flags(proc, "flags", m_out->m_lc_vfs_path.flags,
190521fa314SDavid van Moolenbroek 	    TRUE /*full*/);
191521fa314SDavid van Moolenbroek 
192521fa314SDavid van Moolenbroek 	return CT_DONE;
193521fa314SDavid van Moolenbroek }
194521fa314SDavid van Moolenbroek 
195521fa314SDavid van Moolenbroek /* This function is shared between creat and open. */
196521fa314SDavid van Moolenbroek static void
vfs_open_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)197521fa314SDavid van Moolenbroek vfs_open_in(struct trace_proc * proc, const message * __unused m_out,
198521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
199521fa314SDavid van Moolenbroek {
200521fa314SDavid van Moolenbroek 
201521fa314SDavid van Moolenbroek 	if (!failed)
202521fa314SDavid van Moolenbroek 		put_fd(proc, NULL, m_in->m_type);
203521fa314SDavid van Moolenbroek 	else
204521fa314SDavid van Moolenbroek 		put_result(proc);
205521fa314SDavid van Moolenbroek }
206521fa314SDavid van Moolenbroek 
207521fa314SDavid van Moolenbroek static int
vfs_creat_out(struct trace_proc * proc,const message * m_out)208521fa314SDavid van Moolenbroek vfs_creat_out(struct trace_proc * proc, const message * m_out)
209521fa314SDavid van Moolenbroek {
210521fa314SDavid van Moolenbroek 
211521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_creat.name,
212521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_creat.len);
213521fa314SDavid van Moolenbroek 	put_open_flags(proc, "flags", m_out->m_lc_vfs_creat.flags,
214521fa314SDavid van Moolenbroek 	    TRUE /*full*/);
215521fa314SDavid van Moolenbroek 	put_mode(proc, "mode", m_out->m_lc_vfs_creat.mode);
216521fa314SDavid van Moolenbroek 
217521fa314SDavid van Moolenbroek 	return CT_DONE;
218521fa314SDavid van Moolenbroek }
219521fa314SDavid van Moolenbroek 
220521fa314SDavid van Moolenbroek static int
vfs_close_out(struct trace_proc * proc,const message * m_out)221521fa314SDavid van Moolenbroek vfs_close_out(struct trace_proc * proc, const message * m_out)
222521fa314SDavid van Moolenbroek {
223521fa314SDavid van Moolenbroek 
224521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_close.fd);
225521fa314SDavid van Moolenbroek 
226521fa314SDavid van Moolenbroek 	return CT_DONE;
227521fa314SDavid van Moolenbroek }
228521fa314SDavid van Moolenbroek 
229521fa314SDavid van Moolenbroek /* This function is used for link, rename, and symlink. */
230521fa314SDavid van Moolenbroek static int
vfs_link_out(struct trace_proc * proc,const message * m_out)231521fa314SDavid van Moolenbroek vfs_link_out(struct trace_proc * proc, const message * m_out)
232521fa314SDavid van Moolenbroek {
233521fa314SDavid van Moolenbroek 
234521fa314SDavid van Moolenbroek 	put_buf(proc, "path1", PF_PATH, m_out->m_lc_vfs_link.name1,
235521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_link.len1);
236521fa314SDavid van Moolenbroek 	put_buf(proc, "path2", PF_PATH, m_out->m_lc_vfs_link.name2,
237521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_link.len2);
238521fa314SDavid van Moolenbroek 
239521fa314SDavid van Moolenbroek 	return CT_DONE;
240521fa314SDavid van Moolenbroek }
241521fa314SDavid van Moolenbroek 
242521fa314SDavid van Moolenbroek static int
vfs_path_out(struct trace_proc * proc,const message * m_out)243521fa314SDavid van Moolenbroek vfs_path_out(struct trace_proc * proc, const message * m_out)
244521fa314SDavid van Moolenbroek {
245521fa314SDavid van Moolenbroek 
246521fa314SDavid van Moolenbroek 	put_path(proc, m_out);
247521fa314SDavid van Moolenbroek 
248521fa314SDavid van Moolenbroek 	return CT_DONE;
249521fa314SDavid van Moolenbroek }
250521fa314SDavid van Moolenbroek 
251521fa314SDavid van Moolenbroek static int
vfs_path_mode_out(struct trace_proc * proc,const message * m_out)252521fa314SDavid van Moolenbroek vfs_path_mode_out(struct trace_proc * proc, const message * m_out)
253521fa314SDavid van Moolenbroek {
254521fa314SDavid van Moolenbroek 
255521fa314SDavid van Moolenbroek 	put_path(proc, m_out);
256521fa314SDavid van Moolenbroek 	put_mode(proc, "mode", m_out->m_lc_vfs_path.mode);
257521fa314SDavid van Moolenbroek 
258521fa314SDavid van Moolenbroek 	return CT_DONE;
259521fa314SDavid van Moolenbroek }
260521fa314SDavid van Moolenbroek 
261521fa314SDavid van Moolenbroek void
put_dev(struct trace_proc * proc,const char * name,dev_t dev)262521fa314SDavid van Moolenbroek put_dev(struct trace_proc * proc, const char * name, dev_t dev)
263521fa314SDavid van Moolenbroek {
264521fa314SDavid van Moolenbroek 	devmajor_t major;
265521fa314SDavid van Moolenbroek 	devminor_t minor;
266521fa314SDavid van Moolenbroek 
267521fa314SDavid van Moolenbroek 	major = major(dev);
268521fa314SDavid van Moolenbroek 	minor = minor(dev);
269521fa314SDavid van Moolenbroek 
270521fa314SDavid van Moolenbroek 	/* The value 0 ("no device") should print as "0". */
271521fa314SDavid van Moolenbroek 	if (dev != 0 && makedev(major, minor) == dev && !valuesonly)
272521fa314SDavid van Moolenbroek 		put_value(proc, name, "<%d,%d>", major, minor);
273521fa314SDavid van Moolenbroek 	else
274521fa314SDavid van Moolenbroek 		put_value(proc, name, "%"PRIu64, dev);
275521fa314SDavid van Moolenbroek }
276521fa314SDavid van Moolenbroek 
277521fa314SDavid van Moolenbroek static int
vfs_mknod_out(struct trace_proc * proc,const message * m_out)278521fa314SDavid van Moolenbroek vfs_mknod_out(struct trace_proc * proc, const message * m_out)
279521fa314SDavid van Moolenbroek {
280521fa314SDavid van Moolenbroek 
281521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mknod.name,
282521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_mknod.len);
283521fa314SDavid van Moolenbroek 	put_mode(proc, "mode", m_out->m_lc_vfs_mknod.mode);
284521fa314SDavid van Moolenbroek 	put_dev(proc, "dev", m_out->m_lc_vfs_mknod.device);
285521fa314SDavid van Moolenbroek 
286521fa314SDavid van Moolenbroek 	return CT_DONE;
287521fa314SDavid van Moolenbroek }
288521fa314SDavid van Moolenbroek 
289521fa314SDavid van Moolenbroek static int
vfs_chown_out(struct trace_proc * proc,const message * m_out)290521fa314SDavid van Moolenbroek vfs_chown_out(struct trace_proc * proc, const message * m_out)
291521fa314SDavid van Moolenbroek {
292521fa314SDavid van Moolenbroek 
293521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_chown.name,
294521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_chown.len);
295521fa314SDavid van Moolenbroek 	/* -1 means "keep the current value" so print as signed */
296521fa314SDavid van Moolenbroek 	put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner);
297521fa314SDavid van Moolenbroek 	put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group);
298521fa314SDavid van Moolenbroek 
299521fa314SDavid van Moolenbroek 	return CT_DONE;
300521fa314SDavid van Moolenbroek }
301521fa314SDavid van Moolenbroek 
302521fa314SDavid van Moolenbroek /* TODO: expand this to the full ST_ set. */
303521fa314SDavid van Moolenbroek static const struct flags mount_flags[] = {
304521fa314SDavid van Moolenbroek 	FLAG(MNT_RDONLY),
305521fa314SDavid van Moolenbroek };
306521fa314SDavid van Moolenbroek 
307521fa314SDavid van Moolenbroek static int
vfs_mount_out(struct trace_proc * proc,const message * m_out)308521fa314SDavid van Moolenbroek vfs_mount_out(struct trace_proc * proc, const message * m_out)
309521fa314SDavid van Moolenbroek {
310521fa314SDavid van Moolenbroek 
311521fa314SDavid van Moolenbroek 	put_buf(proc, "special", PF_PATH, m_out->m_lc_vfs_mount.dev,
312521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_mount.devlen);
313521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_mount.path,
314521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_mount.pathlen);
315521fa314SDavid van Moolenbroek 	put_flags(proc, "flags", mount_flags, COUNT(mount_flags), "0x%x",
316521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_mount.flags);
317521fa314SDavid van Moolenbroek 	put_buf(proc, "type", PF_STRING, m_out->m_lc_vfs_mount.type,
318521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_mount.typelen);
319521fa314SDavid van Moolenbroek 	put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_mount.label,
320521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_mount.labellen);
321521fa314SDavid van Moolenbroek 
322521fa314SDavid van Moolenbroek 	return CT_DONE;
323521fa314SDavid van Moolenbroek }
324521fa314SDavid van Moolenbroek 
325521fa314SDavid van Moolenbroek static int
vfs_umount_out(struct trace_proc * proc,const message * m_out)326521fa314SDavid van Moolenbroek vfs_umount_out(struct trace_proc * proc, const message * m_out)
327521fa314SDavid van Moolenbroek {
328521fa314SDavid van Moolenbroek 
329521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_umount.name,
330521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_umount.namelen);
331521fa314SDavid van Moolenbroek 
332521fa314SDavid van Moolenbroek 	return CT_DONE;
333521fa314SDavid van Moolenbroek }
334521fa314SDavid van Moolenbroek 
335521fa314SDavid van Moolenbroek static void
vfs_umount_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)336521fa314SDavid van Moolenbroek vfs_umount_in(struct trace_proc * proc, const message * m_out,
337521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
338521fa314SDavid van Moolenbroek {
339521fa314SDavid van Moolenbroek 
340521fa314SDavid van Moolenbroek 	put_result(proc);
341521fa314SDavid van Moolenbroek 
342521fa314SDavid van Moolenbroek 	if (!failed) {
343521fa314SDavid van Moolenbroek 		put_open(proc, NULL, 0, "(", ", ");
344521fa314SDavid van Moolenbroek 		put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_umount.label,
345521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_umount.labellen);
346521fa314SDavid van Moolenbroek 
347521fa314SDavid van Moolenbroek 		put_close(proc, ")");
348521fa314SDavid van Moolenbroek 	}
349521fa314SDavid van Moolenbroek }
350521fa314SDavid van Moolenbroek 
351521fa314SDavid van Moolenbroek 
352521fa314SDavid van Moolenbroek static const struct flags access_flags[] = {
353521fa314SDavid van Moolenbroek 	FLAG_ZERO(F_OK),
354521fa314SDavid van Moolenbroek 	FLAG(R_OK),
355521fa314SDavid van Moolenbroek 	FLAG(W_OK),
356521fa314SDavid van Moolenbroek 	FLAG(X_OK),
357521fa314SDavid van Moolenbroek };
358521fa314SDavid van Moolenbroek 
359521fa314SDavid van Moolenbroek static int
vfs_access_out(struct trace_proc * proc,const message * m_out)360521fa314SDavid van Moolenbroek vfs_access_out(struct trace_proc * proc, const message * m_out)
361521fa314SDavid van Moolenbroek {
362521fa314SDavid van Moolenbroek 
363521fa314SDavid van Moolenbroek 	put_path(proc, m_out);
364521fa314SDavid van Moolenbroek 	put_flags(proc, "mode", access_flags, COUNT(access_flags), "0x%x",
365521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_path.mode);
366521fa314SDavid van Moolenbroek 
367521fa314SDavid van Moolenbroek 	return CT_DONE;
368521fa314SDavid van Moolenbroek }
369521fa314SDavid van Moolenbroek 
370521fa314SDavid van Moolenbroek static int
vfs_readlink_out(struct trace_proc * proc,const message * m_out)371521fa314SDavid van Moolenbroek vfs_readlink_out(struct trace_proc * proc, const message * m_out)
372521fa314SDavid van Moolenbroek {
373521fa314SDavid van Moolenbroek 
374521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_readlink.name,
375521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_readlink.namelen);
376521fa314SDavid van Moolenbroek 
377521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
378521fa314SDavid van Moolenbroek }
379521fa314SDavid van Moolenbroek 
380521fa314SDavid van Moolenbroek static void
vfs_readlink_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)381521fa314SDavid van Moolenbroek vfs_readlink_in(struct trace_proc * proc, const message * m_out,
382521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
383521fa314SDavid van Moolenbroek {
384521fa314SDavid van Moolenbroek 
385521fa314SDavid van Moolenbroek 	/* The call does not return a string, so do not use PF_STRING here. */
386521fa314SDavid van Moolenbroek 	put_buf(proc, "buf", failed, m_out->m_lc_vfs_readlink.buf,
387521fa314SDavid van Moolenbroek 	    m_in->m_type);
388521fa314SDavid van Moolenbroek 	put_value(proc, "bufsize", "%zd", m_out->m_lc_vfs_readlink.bufsize);
389521fa314SDavid van Moolenbroek 	put_equals(proc);
390521fa314SDavid van Moolenbroek 	put_result(proc);
391521fa314SDavid van Moolenbroek }
392521fa314SDavid van Moolenbroek 
393521fa314SDavid van Moolenbroek static void
put_struct_stat(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)394521fa314SDavid van Moolenbroek put_struct_stat(struct trace_proc * proc, const char * name, int flags,
395521fa314SDavid van Moolenbroek 	vir_bytes addr)
396521fa314SDavid van Moolenbroek {
397521fa314SDavid van Moolenbroek 	struct stat buf;
398521fa314SDavid van Moolenbroek 	int is_special;
399521fa314SDavid van Moolenbroek 
400521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
401521fa314SDavid van Moolenbroek 		return;
402521fa314SDavid van Moolenbroek 
403521fa314SDavid van Moolenbroek 	/*
404521fa314SDavid van Moolenbroek 	 * The combination of struct stat's frequent usage and large number of
405521fa314SDavid van Moolenbroek 	 * fields makes this structure a pain to print.  For now, the idea is
406521fa314SDavid van Moolenbroek 	 * that for verbosity level 0, we print the mode, and the target device
407521fa314SDavid van Moolenbroek 	 * for block/char special files or the file size for all other files.
408521fa314SDavid van Moolenbroek 	 * For higher verbosity levels, largely maintain the structure's own
409521fa314SDavid van Moolenbroek 	 * order of fields.  Violate this general structure printing rule for
410521fa314SDavid van Moolenbroek 	 * some fields though, because the actual field order in struct stat is
411521fa314SDavid van Moolenbroek 	 * downright ridiculous.  Like elsewhere, for verbosity level 1 print
412521fa314SDavid van Moolenbroek 	 * all fields with meaningful values, and for verbosity level 2 just
413521fa314SDavid van Moolenbroek 	 * print everything, including fields that are known to be not yet
414521fa314SDavid van Moolenbroek 	 * supported and fields that contain known values.
415521fa314SDavid van Moolenbroek 	 */
416521fa314SDavid van Moolenbroek 	is_special = (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode));
417521fa314SDavid van Moolenbroek 
418521fa314SDavid van Moolenbroek 	if (verbose > 0) {
419521fa314SDavid van Moolenbroek 		put_dev(proc, "st_dev", buf.st_dev);
420521fa314SDavid van Moolenbroek 		put_value(proc, "st_ino", "%"PRId64, buf.st_ino);
421521fa314SDavid van Moolenbroek 	}
422521fa314SDavid van Moolenbroek 	put_mode(proc, "st_mode", buf.st_mode);
423521fa314SDavid van Moolenbroek 	if (verbose > 0) {
424521fa314SDavid van Moolenbroek 		put_value(proc, "st_nlink", "%u", buf.st_nlink);
425521fa314SDavid van Moolenbroek 		put_value(proc, "st_uid", "%u", buf.st_uid);
426521fa314SDavid van Moolenbroek 		put_value(proc, "st_gid", "%u", buf.st_gid);
427521fa314SDavid van Moolenbroek 	}
428521fa314SDavid van Moolenbroek 	if (is_special || verbose > 1)
429521fa314SDavid van Moolenbroek 		put_dev(proc, "st_rdev", buf.st_rdev);
430521fa314SDavid van Moolenbroek 	if (verbose > 0) {
431521fa314SDavid van Moolenbroek 		/*
432521fa314SDavid van Moolenbroek 		 * TODO: print the nanosecond part, but possibly only if we are
433521fa314SDavid van Moolenbroek 		 * not actually interpreting the time as a date (another TODO),
434521fa314SDavid van Moolenbroek 		 * and/or possibly only with verbose > 1 (largely unsupported).
435521fa314SDavid van Moolenbroek 		 */
436521fa314SDavid van Moolenbroek 		put_time(proc, "st_atime", buf.st_atime);
437521fa314SDavid van Moolenbroek 		put_time(proc, "st_mtime", buf.st_mtime);
438521fa314SDavid van Moolenbroek 		put_time(proc, "st_ctime", buf.st_ctime);
439521fa314SDavid van Moolenbroek 	}
440521fa314SDavid van Moolenbroek 	if (verbose > 1) /* not yet supported on MINIX3 */
441521fa314SDavid van Moolenbroek 		put_time(proc, "st_birthtime", buf.st_birthtime);
442521fa314SDavid van Moolenbroek 	if (!is_special || verbose > 1)
443521fa314SDavid van Moolenbroek 		put_value(proc, "st_size", "%"PRId64, buf.st_size);
444521fa314SDavid van Moolenbroek 	if (verbose > 0) {
445521fa314SDavid van Moolenbroek 		put_value(proc, "st_blocks", "%"PRId64, buf.st_blocks);
446521fa314SDavid van Moolenbroek 		put_value(proc, "st_blksize", "%"PRId32, buf.st_blksize);
447521fa314SDavid van Moolenbroek 	}
448521fa314SDavid van Moolenbroek 	if (verbose > 1) {
449521fa314SDavid van Moolenbroek 		put_value(proc, "st_flags", "%"PRIu32, buf.st_flags);
450521fa314SDavid van Moolenbroek 		put_value(proc, "st_gen", "%"PRIu32, buf.st_gen);
451521fa314SDavid van Moolenbroek 	}
452521fa314SDavid van Moolenbroek 
453521fa314SDavid van Moolenbroek 	put_close_struct(proc, verbose > 1);
454521fa314SDavid van Moolenbroek }
455521fa314SDavid van Moolenbroek 
456521fa314SDavid van Moolenbroek static int
vfs_stat_out(struct trace_proc * proc,const message * m_out)457521fa314SDavid van Moolenbroek vfs_stat_out(struct trace_proc * proc, const message * m_out)
458521fa314SDavid van Moolenbroek {
459521fa314SDavid van Moolenbroek 
460521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_stat.name,
461521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_stat.len);
462521fa314SDavid van Moolenbroek 
463521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
464521fa314SDavid van Moolenbroek }
465521fa314SDavid van Moolenbroek 
466521fa314SDavid van Moolenbroek static void
vfs_stat_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)467521fa314SDavid van Moolenbroek vfs_stat_in(struct trace_proc * proc, const message * m_out,
468521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
469521fa314SDavid van Moolenbroek {
470521fa314SDavid van Moolenbroek 
471521fa314SDavid van Moolenbroek 	put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_stat.buf);
472521fa314SDavid van Moolenbroek 	put_equals(proc);
473521fa314SDavid van Moolenbroek 	put_result(proc);
474521fa314SDavid van Moolenbroek }
475521fa314SDavid van Moolenbroek 
476521fa314SDavid van Moolenbroek static int
vfs_fstat_out(struct trace_proc * proc,const message * m_out)477521fa314SDavid van Moolenbroek vfs_fstat_out(struct trace_proc * proc, const message * m_out)
478521fa314SDavid van Moolenbroek {
479521fa314SDavid van Moolenbroek 
480521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_fstat.fd);
481521fa314SDavid van Moolenbroek 
482521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
483521fa314SDavid van Moolenbroek }
484521fa314SDavid van Moolenbroek 
485521fa314SDavid van Moolenbroek static void
vfs_fstat_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)486521fa314SDavid van Moolenbroek vfs_fstat_in(struct trace_proc * proc, const message * m_out,
487521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
488521fa314SDavid van Moolenbroek {
489521fa314SDavid van Moolenbroek 
490521fa314SDavid van Moolenbroek 	put_struct_stat(proc, "buf", failed, m_out->m_lc_vfs_fstat.buf);
491521fa314SDavid van Moolenbroek 	put_equals(proc);
492521fa314SDavid van Moolenbroek 	put_result(proc);
493521fa314SDavid van Moolenbroek }
494521fa314SDavid van Moolenbroek 
495521fa314SDavid van Moolenbroek static int
vfs_ioctl_out(struct trace_proc * proc,const message * m_out)496521fa314SDavid van Moolenbroek vfs_ioctl_out(struct trace_proc * proc, const message * m_out)
497521fa314SDavid van Moolenbroek {
498521fa314SDavid van Moolenbroek 
499521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_ioctl.fd);
500521fa314SDavid van Moolenbroek 	put_ioctl_req(proc, "req", m_out->m_lc_vfs_ioctl.req,
501521fa314SDavid van Moolenbroek 	    FALSE /*is_svrctl*/);
502521fa314SDavid van Moolenbroek 	return put_ioctl_arg_out(proc, "arg", m_out->m_lc_vfs_ioctl.req,
503521fa314SDavid van Moolenbroek 	    (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/);
504521fa314SDavid van Moolenbroek }
505521fa314SDavid van Moolenbroek 
506521fa314SDavid van Moolenbroek static void
vfs_ioctl_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)507521fa314SDavid van Moolenbroek vfs_ioctl_in(struct trace_proc * proc, const message * m_out,
508521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
509521fa314SDavid van Moolenbroek {
510521fa314SDavid van Moolenbroek 
511521fa314SDavid van Moolenbroek 	put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_vfs_ioctl.req,
512521fa314SDavid van Moolenbroek 	    (vir_bytes)m_out->m_lc_vfs_ioctl.arg, FALSE /*is_svrctl*/);
513521fa314SDavid van Moolenbroek }
514521fa314SDavid van Moolenbroek 
515521fa314SDavid van Moolenbroek static void
put_fcntl_cmd(struct trace_proc * proc,const char * name,int cmd)516521fa314SDavid van Moolenbroek put_fcntl_cmd(struct trace_proc * proc, const char * name, int cmd)
517521fa314SDavid van Moolenbroek {
518521fa314SDavid van Moolenbroek 	const char *text = NULL;
519521fa314SDavid van Moolenbroek 
520521fa314SDavid van Moolenbroek 	if (!valuesonly) {
521521fa314SDavid van Moolenbroek 		switch (cmd) {
522521fa314SDavid van Moolenbroek 		TEXT(F_DUPFD);
523521fa314SDavid van Moolenbroek 		TEXT(F_GETFD);
524521fa314SDavid van Moolenbroek 		TEXT(F_SETFD);
525521fa314SDavid van Moolenbroek 		TEXT(F_GETFL);
526521fa314SDavid van Moolenbroek 		TEXT(F_SETFL);
527521fa314SDavid van Moolenbroek 		TEXT(F_GETOWN);
528521fa314SDavid van Moolenbroek 		TEXT(F_SETOWN);
529521fa314SDavid van Moolenbroek 		TEXT(F_GETLK);
530521fa314SDavid van Moolenbroek 		TEXT(F_SETLK);
531521fa314SDavid van Moolenbroek 		TEXT(F_SETLKW);
532521fa314SDavid van Moolenbroek 		TEXT(F_CLOSEM);
533521fa314SDavid van Moolenbroek 		TEXT(F_MAXFD);
534521fa314SDavid van Moolenbroek 		TEXT(F_DUPFD_CLOEXEC);
535521fa314SDavid van Moolenbroek 		TEXT(F_GETNOSIGPIPE);
536521fa314SDavid van Moolenbroek 		TEXT(F_SETNOSIGPIPE);
537521fa314SDavid van Moolenbroek 		TEXT(F_FREESP);
538521fa314SDavid van Moolenbroek 		TEXT(F_FLUSH_FS_CACHE);
539521fa314SDavid van Moolenbroek 		}
540521fa314SDavid van Moolenbroek 	}
541521fa314SDavid van Moolenbroek 
542521fa314SDavid van Moolenbroek 	if (text != NULL)
543521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
544521fa314SDavid van Moolenbroek 	else
545521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", cmd);
546521fa314SDavid van Moolenbroek }
547521fa314SDavid van Moolenbroek 
548521fa314SDavid van Moolenbroek static const struct flags fd_flags[] = {
549521fa314SDavid van Moolenbroek 	FLAG(FD_CLOEXEC),
550521fa314SDavid van Moolenbroek };
551521fa314SDavid van Moolenbroek 
552521fa314SDavid van Moolenbroek #define put_fd_flags(p, n, v) \
553521fa314SDavid van Moolenbroek 	put_flags(p, n, fd_flags, COUNT(fd_flags), "0x%x", v)
554521fa314SDavid van Moolenbroek 
555521fa314SDavid van Moolenbroek static void
put_flock_type(struct trace_proc * proc,const char * name,int type)556521fa314SDavid van Moolenbroek put_flock_type(struct trace_proc * proc, const char * name, int type)
557521fa314SDavid van Moolenbroek {
558521fa314SDavid van Moolenbroek 	const char *text = NULL;
559521fa314SDavid van Moolenbroek 
560521fa314SDavid van Moolenbroek 	if (!valuesonly) {
561521fa314SDavid van Moolenbroek 		switch (type) {
562521fa314SDavid van Moolenbroek 		TEXT(F_RDLCK);
563521fa314SDavid van Moolenbroek 		TEXT(F_UNLCK);
564521fa314SDavid van Moolenbroek 		TEXT(F_WRLCK);
565521fa314SDavid van Moolenbroek 		}
566521fa314SDavid van Moolenbroek 	}
567521fa314SDavid van Moolenbroek 
568521fa314SDavid van Moolenbroek 	if (text != NULL)
569521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
570521fa314SDavid van Moolenbroek 	else
571521fa314SDavid van Moolenbroek 		put_value(proc, name, "%d", type);
572521fa314SDavid van Moolenbroek }
573521fa314SDavid van Moolenbroek 
574521fa314SDavid van Moolenbroek /*
575521fa314SDavid van Moolenbroek  * With PF_FULL, also print l_pid, unless l_type is F_UNLCK in which case
576521fa314SDavid van Moolenbroek  * only that type is printed.   With PF_ALT, print only l_whence/l_start/l_len.
577521fa314SDavid van Moolenbroek  */
578521fa314SDavid van Moolenbroek static void
put_struct_flock(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)579521fa314SDavid van Moolenbroek put_struct_flock(struct trace_proc * proc, const char * name, int flags,
580521fa314SDavid van Moolenbroek 	vir_bytes addr)
581521fa314SDavid van Moolenbroek {
582521fa314SDavid van Moolenbroek 	struct flock flock;
583521fa314SDavid van Moolenbroek 	int limited;
584521fa314SDavid van Moolenbroek 
585521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &flock, sizeof(flock)))
586521fa314SDavid van Moolenbroek 		return;
587521fa314SDavid van Moolenbroek 
588521fa314SDavid van Moolenbroek 	limited = ((flags & PF_FULL) && flock.l_type == F_UNLCK);
589521fa314SDavid van Moolenbroek 
590521fa314SDavid van Moolenbroek 	if (!(flags & PF_ALT))
591521fa314SDavid van Moolenbroek 		put_flock_type(proc, "l_type", flock.l_type);
592521fa314SDavid van Moolenbroek 	if (!limited) {
593521fa314SDavid van Moolenbroek 		put_lseek_whence(proc, "l_whence", flock.l_whence);
594521fa314SDavid van Moolenbroek 		put_value(proc, "l_start", "%"PRId64, flock.l_start);
595521fa314SDavid van Moolenbroek 		put_value(proc, "l_len", "%"PRId64, flock.l_len);
596521fa314SDavid van Moolenbroek 		if (flags & PF_FULL)
597521fa314SDavid van Moolenbroek 			put_value(proc, "l_pid", "%d", flock.l_pid);
598521fa314SDavid van Moolenbroek 	}
599521fa314SDavid van Moolenbroek 
600521fa314SDavid van Moolenbroek 	put_close_struct(proc, TRUE /*all*/);
601521fa314SDavid van Moolenbroek }
602521fa314SDavid van Moolenbroek 
603521fa314SDavid van Moolenbroek static int
vfs_fcntl_out(struct trace_proc * proc,const message * m_out)604521fa314SDavid van Moolenbroek vfs_fcntl_out(struct trace_proc * proc, const message * m_out)
605521fa314SDavid van Moolenbroek {
606521fa314SDavid van Moolenbroek 
607521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_fcntl.fd);
608521fa314SDavid van Moolenbroek 	put_fcntl_cmd(proc, "cmd", m_out->m_lc_vfs_fcntl.cmd);
609521fa314SDavid van Moolenbroek 
610521fa314SDavid van Moolenbroek 	switch (m_out->m_lc_vfs_fcntl.cmd) {
611521fa314SDavid van Moolenbroek 	case F_DUPFD:
612424cad2cSDavid van Moolenbroek 	case F_DUPFD_CLOEXEC:
613521fa314SDavid van Moolenbroek 		put_fd(proc, "fd2", m_out->m_lc_vfs_fcntl.arg_int);
614521fa314SDavid van Moolenbroek 		break;
615521fa314SDavid van Moolenbroek 	case F_SETFD:
616521fa314SDavid van Moolenbroek 		put_fd_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int);
617521fa314SDavid van Moolenbroek 		break;
618521fa314SDavid van Moolenbroek 	case F_SETFL:
619521fa314SDavid van Moolenbroek 		/*
620521fa314SDavid van Moolenbroek 		 * One of those difficult cases: the access mode is ignored, so
621521fa314SDavid van Moolenbroek 		 * we don't want to print O_RDONLY if it is not given.  On the
622521fa314SDavid van Moolenbroek 		 * other hand, fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_..) is
623521fa314SDavid van Moolenbroek 		 * a fairly common construction, in which case we don't want to
624521fa314SDavid van Moolenbroek 		 * print eg O_..|0x2 if the access mode is O_RDWR.  Thus, we
625521fa314SDavid van Moolenbroek 		 * compromise: show the access mode if any of its bits are set.
626521fa314SDavid van Moolenbroek 		 */
627521fa314SDavid van Moolenbroek 		put_open_flags(proc, "flags", m_out->m_lc_vfs_fcntl.arg_int,
628521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_fcntl.arg_int & O_ACCMODE /*full*/);
629521fa314SDavid van Moolenbroek 		break;
630521fa314SDavid van Moolenbroek 	case F_SETLK:
631521fa314SDavid van Moolenbroek 	case F_SETLKW:
632521fa314SDavid van Moolenbroek 		put_struct_flock(proc, "lkp", 0,
633521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_fcntl.arg_ptr);
634521fa314SDavid van Moolenbroek 		break;
635521fa314SDavid van Moolenbroek 	case F_FREESP:
636521fa314SDavid van Moolenbroek 		put_struct_flock(proc, "lkp", PF_ALT,
637521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_fcntl.arg_ptr);
638521fa314SDavid van Moolenbroek 		break;
639521fa314SDavid van Moolenbroek 	case F_SETNOSIGPIPE:
640521fa314SDavid van Moolenbroek 		put_value(proc, "arg", "%d", m_out->m_lc_vfs_fcntl.arg_int);
641521fa314SDavid van Moolenbroek 		break;
642521fa314SDavid van Moolenbroek 	}
643521fa314SDavid van Moolenbroek 
644521fa314SDavid van Moolenbroek 	return (m_out->m_lc_vfs_fcntl.cmd != F_GETLK) ? CT_DONE : CT_NOTDONE;
645521fa314SDavid van Moolenbroek }
646521fa314SDavid van Moolenbroek 
647521fa314SDavid van Moolenbroek static void
vfs_fcntl_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)648521fa314SDavid van Moolenbroek vfs_fcntl_in(struct trace_proc * proc, const message * m_out,
649521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
650521fa314SDavid van Moolenbroek {
651521fa314SDavid van Moolenbroek 
652521fa314SDavid van Moolenbroek 	switch (m_out->m_lc_vfs_fcntl.cmd) {
653521fa314SDavid van Moolenbroek 	case F_GETFD:
654521fa314SDavid van Moolenbroek 		if (failed)
655521fa314SDavid van Moolenbroek 			break;
656521fa314SDavid van Moolenbroek 		put_fd_flags(proc, NULL, m_in->m_type);
657521fa314SDavid van Moolenbroek 		return;
658521fa314SDavid van Moolenbroek 	case F_GETFL:
659521fa314SDavid van Moolenbroek 		if (failed)
660521fa314SDavid van Moolenbroek 			break;
661521fa314SDavid van Moolenbroek 		put_open_flags(proc, NULL, m_in->m_type, TRUE /*full*/);
662521fa314SDavid van Moolenbroek 		return;
663521fa314SDavid van Moolenbroek 	case F_GETLK:
664521fa314SDavid van Moolenbroek 		put_struct_flock(proc, "lkp", failed | PF_FULL,
665521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_fcntl.arg_ptr);
666521fa314SDavid van Moolenbroek 		put_equals(proc);
667521fa314SDavid van Moolenbroek 		break;
668521fa314SDavid van Moolenbroek 	}
669521fa314SDavid van Moolenbroek 
670521fa314SDavid van Moolenbroek 	put_result(proc);
671521fa314SDavid van Moolenbroek }
672521fa314SDavid van Moolenbroek 
673521fa314SDavid van Moolenbroek static int
vfs_pipe2_out(struct trace_proc * __unused proc,const message * __unused m_out)674521fa314SDavid van Moolenbroek vfs_pipe2_out(struct trace_proc * __unused proc,
675521fa314SDavid van Moolenbroek 	const message * __unused m_out)
676521fa314SDavid van Moolenbroek {
677521fa314SDavid van Moolenbroek 
678521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
679521fa314SDavid van Moolenbroek }
680521fa314SDavid van Moolenbroek 
681521fa314SDavid van Moolenbroek static void
vfs_pipe2_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)682521fa314SDavid van Moolenbroek vfs_pipe2_in(struct trace_proc * proc, const message * m_out,
683521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
684521fa314SDavid van Moolenbroek {
685521fa314SDavid van Moolenbroek 
686521fa314SDavid van Moolenbroek 	if (!failed) {
687521fa314SDavid van Moolenbroek 		put_open(proc, "fd", PF_NONAME, "[", ", ");
688c33d6ef3SDavid van Moolenbroek 		put_fd(proc, "rfd", m_in->m_vfs_lc_fdpair.fd0);
689c33d6ef3SDavid van Moolenbroek 		put_fd(proc, "wfd", m_in->m_vfs_lc_fdpair.fd1);
690521fa314SDavid van Moolenbroek 		put_close(proc, "]");
691521fa314SDavid van Moolenbroek 	} else
692521fa314SDavid van Moolenbroek 		put_field(proc, "fd", "&..");
693521fa314SDavid van Moolenbroek 	put_open_flags(proc, "flags", m_out->m_lc_vfs_pipe2.flags,
694521fa314SDavid van Moolenbroek 	    FALSE /*full*/);
695521fa314SDavid van Moolenbroek 	put_equals(proc);
696521fa314SDavid van Moolenbroek 	put_result(proc);
697521fa314SDavid van Moolenbroek }
698521fa314SDavid van Moolenbroek 
699521fa314SDavid van Moolenbroek static int
vfs_umask_out(struct trace_proc * proc,const message * m_out)700521fa314SDavid van Moolenbroek vfs_umask_out(struct trace_proc * proc, const message * m_out)
701521fa314SDavid van Moolenbroek {
702521fa314SDavid van Moolenbroek 
703521fa314SDavid van Moolenbroek 	put_mode(proc, NULL, m_out->m_lc_vfs_umask.mask);
704521fa314SDavid van Moolenbroek 
705521fa314SDavid van Moolenbroek 	return CT_DONE;
706521fa314SDavid van Moolenbroek }
707521fa314SDavid van Moolenbroek 
708521fa314SDavid van Moolenbroek static void
vfs_umask_in(struct trace_proc * proc,const message * __unused m_out,const message * m_in,int failed)709521fa314SDavid van Moolenbroek vfs_umask_in(struct trace_proc * proc, const message * __unused m_out,
710521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
711521fa314SDavid van Moolenbroek {
712521fa314SDavid van Moolenbroek 
713521fa314SDavid van Moolenbroek 	if (!failed)
714521fa314SDavid van Moolenbroek 		put_mode(proc, NULL, m_in->m_type);
715521fa314SDavid van Moolenbroek 	else
716521fa314SDavid van Moolenbroek 		put_result(proc);
717521fa314SDavid van Moolenbroek 
718521fa314SDavid van Moolenbroek }
719521fa314SDavid van Moolenbroek 
720521fa314SDavid van Moolenbroek static void
put_dirent_type(struct trace_proc * proc,const char * name,unsigned int type)721521fa314SDavid van Moolenbroek put_dirent_type(struct trace_proc * proc, const char * name, unsigned int type)
722521fa314SDavid van Moolenbroek {
723521fa314SDavid van Moolenbroek 	const char *text = NULL;
724521fa314SDavid van Moolenbroek 
725521fa314SDavid van Moolenbroek 	if (!valuesonly) {
726521fa314SDavid van Moolenbroek 		switch (type) {
727521fa314SDavid van Moolenbroek 		TEXT(DT_UNKNOWN);
728521fa314SDavid van Moolenbroek 		TEXT(DT_FIFO);
729521fa314SDavid van Moolenbroek 		TEXT(DT_CHR);
730521fa314SDavid van Moolenbroek 		TEXT(DT_DIR);
731521fa314SDavid van Moolenbroek 		TEXT(DT_BLK);
732521fa314SDavid van Moolenbroek 		TEXT(DT_REG);
733521fa314SDavid van Moolenbroek 		TEXT(DT_LNK);
734521fa314SDavid van Moolenbroek 		TEXT(DT_SOCK);
735521fa314SDavid van Moolenbroek 		TEXT(DT_WHT);
736521fa314SDavid van Moolenbroek 		}
737521fa314SDavid van Moolenbroek 	}
738521fa314SDavid van Moolenbroek 
739521fa314SDavid van Moolenbroek 	if (text != NULL)
740521fa314SDavid van Moolenbroek 		put_field(proc, name, text);
741521fa314SDavid van Moolenbroek 	else
742521fa314SDavid van Moolenbroek 		put_value(proc, name, "%u", type);
743521fa314SDavid van Moolenbroek }
744521fa314SDavid van Moolenbroek 
745521fa314SDavid van Moolenbroek static void
put_struct_dirent(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)746521fa314SDavid van Moolenbroek put_struct_dirent(struct trace_proc * proc, const char *name, int flags,
747521fa314SDavid van Moolenbroek 	vir_bytes addr)
748521fa314SDavid van Moolenbroek {
749521fa314SDavid van Moolenbroek 	struct dirent dirent;
750521fa314SDavid van Moolenbroek 
751521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &dirent, sizeof(dirent)))
752521fa314SDavid van Moolenbroek 		return;
753521fa314SDavid van Moolenbroek 
754521fa314SDavid van Moolenbroek 	if (verbose > 0)
755521fa314SDavid van Moolenbroek 		put_value(proc, "d_fileno", "%"PRIu64, dirent.d_fileno);
756521fa314SDavid van Moolenbroek 	if (verbose > 1) {
757521fa314SDavid van Moolenbroek 		put_value(proc, "d_reclen", "%u", dirent.d_reclen);
758521fa314SDavid van Moolenbroek 		put_value(proc, "d_namlen", "%u", dirent.d_namlen);
759521fa314SDavid van Moolenbroek 	}
760521fa314SDavid van Moolenbroek 	if (verbose >= 1 + (dirent.d_type == DT_UNKNOWN))
761521fa314SDavid van Moolenbroek 		put_dirent_type(proc, "d_type", dirent.d_type);
762521fa314SDavid van Moolenbroek 	put_buf(proc, "d_name", PF_LOCADDR, (vir_bytes)dirent.d_name,
763521fa314SDavid van Moolenbroek 	    MIN(dirent.d_namlen, sizeof(dirent.d_name)));
764521fa314SDavid van Moolenbroek 
765521fa314SDavid van Moolenbroek 	put_close_struct(proc, verbose > 1);
766521fa314SDavid van Moolenbroek }
767521fa314SDavid van Moolenbroek 
768521fa314SDavid van Moolenbroek static void
put_dirent_array(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,ssize_t size)769521fa314SDavid van Moolenbroek put_dirent_array(struct trace_proc * proc, const char * name, int flags,
770521fa314SDavid van Moolenbroek 	vir_bytes addr, ssize_t size)
771521fa314SDavid van Moolenbroek {
772521fa314SDavid van Moolenbroek 	struct dirent dirent;
773521fa314SDavid van Moolenbroek 	unsigned count, max;
774521fa314SDavid van Moolenbroek 	ssize_t off, chunk;
775521fa314SDavid van Moolenbroek 
776521fa314SDavid van Moolenbroek 	if ((flags & PF_FAILED) || valuesonly > 1 || size < 0) {
777521fa314SDavid van Moolenbroek 		put_ptr(proc, name, addr);
778521fa314SDavid van Moolenbroek 
779521fa314SDavid van Moolenbroek 		return;
780521fa314SDavid van Moolenbroek 	}
781521fa314SDavid van Moolenbroek 
782521fa314SDavid van Moolenbroek 	if (size == 0) {
783521fa314SDavid van Moolenbroek 		put_field(proc, name, "[]");
784521fa314SDavid van Moolenbroek 
785521fa314SDavid van Moolenbroek 		return;
786521fa314SDavid van Moolenbroek 	}
787521fa314SDavid van Moolenbroek 
788521fa314SDavid van Moolenbroek 	if (verbose == 0)
789521fa314SDavid van Moolenbroek 		max = 0; /* TODO: should we set this to 1 instead? */
790521fa314SDavid van Moolenbroek 	else if (verbose == 1)
791521fa314SDavid van Moolenbroek 		max = 3; /* low; just to give an indication where we are */
792521fa314SDavid van Moolenbroek 	else
793521fa314SDavid van Moolenbroek 		max = INT_MAX;
794521fa314SDavid van Moolenbroek 
795521fa314SDavid van Moolenbroek 	/*
796521fa314SDavid van Moolenbroek 	 * TODO: as is, this is highly inefficient, as we are typically copying
797521fa314SDavid van Moolenbroek 	 * in the same pieces of memory in repeatedly..
798521fa314SDavid van Moolenbroek 	 */
799521fa314SDavid van Moolenbroek 	count = 0;
800521fa314SDavid van Moolenbroek 	for (off = 0; off < size; off += chunk) {
801521fa314SDavid van Moolenbroek 		chunk = size - off;
802b58e161cSDavid van Moolenbroek 		if ((size_t)chunk > sizeof(dirent))
803b58e161cSDavid van Moolenbroek 			chunk = (ssize_t)sizeof(dirent);
804b58e161cSDavid van Moolenbroek 		if ((size_t)chunk < _DIRENT_MINSIZE(&dirent))
805521fa314SDavid van Moolenbroek 			break;
806521fa314SDavid van Moolenbroek 
807521fa314SDavid van Moolenbroek 		if (mem_get_data(proc->pid, addr + off, &dirent, chunk) < 0) {
808521fa314SDavid van Moolenbroek 			if (off == 0) {
809521fa314SDavid van Moolenbroek 				put_ptr(proc, name, addr);
810521fa314SDavid van Moolenbroek 
811521fa314SDavid van Moolenbroek 				return;
812521fa314SDavid van Moolenbroek 			}
813521fa314SDavid van Moolenbroek 
814521fa314SDavid van Moolenbroek 			break;
815521fa314SDavid van Moolenbroek 		}
816521fa314SDavid van Moolenbroek 
817521fa314SDavid van Moolenbroek 		if (off == 0)
818521fa314SDavid van Moolenbroek 			put_open(proc, name, PF_NONAME, "[", ", ");
819521fa314SDavid van Moolenbroek 
820521fa314SDavid van Moolenbroek 		if (count < max)
821521fa314SDavid van Moolenbroek 			put_struct_dirent(proc, NULL, PF_LOCADDR,
822521fa314SDavid van Moolenbroek 			    (vir_bytes)&dirent);
823521fa314SDavid van Moolenbroek 
824521fa314SDavid van Moolenbroek 		if (chunk > dirent.d_reclen)
825521fa314SDavid van Moolenbroek 			chunk = dirent.d_reclen;
826521fa314SDavid van Moolenbroek 		count++;
827521fa314SDavid van Moolenbroek 	}
828521fa314SDavid van Moolenbroek 
829521fa314SDavid van Moolenbroek 	if (off < size)
830521fa314SDavid van Moolenbroek 		put_tail(proc, 0, 0);
831521fa314SDavid van Moolenbroek 	else if (count > max)
832521fa314SDavid van Moolenbroek 		put_tail(proc, count, max);
833521fa314SDavid van Moolenbroek 	put_close(proc, "]");
834521fa314SDavid van Moolenbroek }
835521fa314SDavid van Moolenbroek 
836521fa314SDavid van Moolenbroek static int
vfs_getdents_out(struct trace_proc * proc,const message * m_out)837521fa314SDavid van Moolenbroek vfs_getdents_out(struct trace_proc * proc, const message * m_out)
838521fa314SDavid van Moolenbroek {
839521fa314SDavid van Moolenbroek 
840521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_readwrite.fd);
841521fa314SDavid van Moolenbroek 
842521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
843521fa314SDavid van Moolenbroek }
844521fa314SDavid van Moolenbroek 
845521fa314SDavid van Moolenbroek static void
vfs_getdents_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)846521fa314SDavid van Moolenbroek vfs_getdents_in(struct trace_proc * proc, const message * m_out,
847521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
848521fa314SDavid van Moolenbroek {
849521fa314SDavid van Moolenbroek 
850521fa314SDavid van Moolenbroek 	put_dirent_array(proc, "buf", failed, m_out->m_lc_vfs_readwrite.buf,
851521fa314SDavid van Moolenbroek 	    m_in->m_type);
852521fa314SDavid van Moolenbroek 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_readwrite.len);
853521fa314SDavid van Moolenbroek 	put_equals(proc);
854521fa314SDavid van Moolenbroek 	put_result(proc);
855521fa314SDavid van Moolenbroek }
856521fa314SDavid van Moolenbroek 
857521fa314SDavid van Moolenbroek static void
put_fd_set(struct trace_proc * proc,const char * name,vir_bytes addr,int nfds)858521fa314SDavid van Moolenbroek put_fd_set(struct trace_proc * proc, const char * name, vir_bytes addr,
859521fa314SDavid van Moolenbroek 	int nfds)
860521fa314SDavid van Moolenbroek {
861521fa314SDavid van Moolenbroek 	fd_set set;
862521fa314SDavid van Moolenbroek 	size_t off;
863521fa314SDavid van Moolenbroek 	unsigned int i, j, words, count, max;
864521fa314SDavid van Moolenbroek 
865521fa314SDavid van Moolenbroek 	if (addr == 0 || nfds < 0) {
866521fa314SDavid van Moolenbroek 		put_ptr(proc, name, addr);
867521fa314SDavid van Moolenbroek 
868521fa314SDavid van Moolenbroek 		return;
869521fa314SDavid van Moolenbroek 	}
870521fa314SDavid van Moolenbroek 
871521fa314SDavid van Moolenbroek 	/*
872521fa314SDavid van Moolenbroek 	 * Each process may define its own FD_SETSIZE, so our fd_set may be of
873521fa314SDavid van Moolenbroek 	 * a different size than theirs.  Thus, we copy at a granularity known
874521fa314SDavid van Moolenbroek 	 * to be valid in any case: a single word of bits.  We make the
875521fa314SDavid van Moolenbroek 	 * assumption that fd_set consists purely of bits, so that we can use
876521fa314SDavid van Moolenbroek 	 * the second (and so on) bit word as an fd_set by itself.
877521fa314SDavid van Moolenbroek 	 */
878521fa314SDavid van Moolenbroek 	words = (nfds + NFDBITS - 1) / NFDBITS;
879521fa314SDavid van Moolenbroek 
880521fa314SDavid van Moolenbroek 	count = 0;
881521fa314SDavid van Moolenbroek 
882521fa314SDavid van Moolenbroek 	if (verbose == 0)
883521fa314SDavid van Moolenbroek 		max = 16;
884521fa314SDavid van Moolenbroek 	else if (verbose == 1)
885521fa314SDavid van Moolenbroek 		max = FD_SETSIZE;
886521fa314SDavid van Moolenbroek 	else
887521fa314SDavid van Moolenbroek 		max = INT_MAX;
888521fa314SDavid van Moolenbroek 
889521fa314SDavid van Moolenbroek 	/* TODO: copy in more at once, but stick to fd_mask boundaries. */
890521fa314SDavid van Moolenbroek 	for (off = 0, i = 0; i < words; i++, off += sizeof(fd_mask)) {
891521fa314SDavid van Moolenbroek 		if (mem_get_data(proc->pid, addr + off, &set,
892521fa314SDavid van Moolenbroek 		    sizeof(fd_mask)) != 0) {
893521fa314SDavid van Moolenbroek 			if (count == 0) {
894521fa314SDavid van Moolenbroek 				put_ptr(proc, name, addr);
895521fa314SDavid van Moolenbroek 
896521fa314SDavid van Moolenbroek 				return;
897521fa314SDavid van Moolenbroek 			}
898521fa314SDavid van Moolenbroek 
899521fa314SDavid van Moolenbroek 			break;
900521fa314SDavid van Moolenbroek 		}
901521fa314SDavid van Moolenbroek 
902521fa314SDavid van Moolenbroek 		for (j = 0; j < NFDBITS; j++) {
903521fa314SDavid van Moolenbroek 			if (FD_ISSET(j, &set)) {
904521fa314SDavid van Moolenbroek 				if (count == 0)
905521fa314SDavid van Moolenbroek 					put_open(proc, name, PF_NONAME, "[",
906521fa314SDavid van Moolenbroek 					    " ");
907521fa314SDavid van Moolenbroek 
908521fa314SDavid van Moolenbroek 				if (count < max)
909521fa314SDavid van Moolenbroek 					put_fd(proc, NULL, i * NFDBITS + j);
910521fa314SDavid van Moolenbroek 
911521fa314SDavid van Moolenbroek 				count++;
912521fa314SDavid van Moolenbroek 			}
913521fa314SDavid van Moolenbroek 		}
914521fa314SDavid van Moolenbroek 	}
915521fa314SDavid van Moolenbroek 
916521fa314SDavid van Moolenbroek 	/*
917521fa314SDavid van Moolenbroek 	 * The empty set should print as "[]".  If copying any part failed, it
918521fa314SDavid van Moolenbroek 	 * should print as "[x, ..(?)]" where x is the set printed so far, if
919521fa314SDavid van Moolenbroek 	 * any.  If copying never failed, and we did not print all fds in the
920521fa314SDavid van Moolenbroek 	 * set, print the remaining count n as "[x, ..(+n)]" at the end.
921521fa314SDavid van Moolenbroek 	 */
922521fa314SDavid van Moolenbroek 	if (count == 0)
923521fa314SDavid van Moolenbroek 		put_open(proc, name, PF_NONAME, "[", " ");
924521fa314SDavid van Moolenbroek 
925521fa314SDavid van Moolenbroek 	if (i < words)
926521fa314SDavid van Moolenbroek 		put_tail(proc, 0, 0);
927521fa314SDavid van Moolenbroek 	else if (count > max)
928521fa314SDavid van Moolenbroek 		put_tail(proc, count, max);
929521fa314SDavid van Moolenbroek 
930521fa314SDavid van Moolenbroek 	put_close(proc, "]");
931521fa314SDavid van Moolenbroek }
932521fa314SDavid van Moolenbroek 
933521fa314SDavid van Moolenbroek static int
vfs_select_out(struct trace_proc * proc,const message * m_out)934521fa314SDavid van Moolenbroek vfs_select_out(struct trace_proc * proc, const message * m_out)
935521fa314SDavid van Moolenbroek {
936521fa314SDavid van Moolenbroek 	int nfds;
937521fa314SDavid van Moolenbroek 
938521fa314SDavid van Moolenbroek 	nfds = m_out->m_lc_vfs_select.nfds;
939521fa314SDavid van Moolenbroek 
940521fa314SDavid van Moolenbroek 	put_fd(proc, "nfds", nfds); /* not really a file descriptor.. */
941521fa314SDavid van Moolenbroek 	put_fd_set(proc, "readfds",
942521fa314SDavid van Moolenbroek 	    (vir_bytes)m_out->m_lc_vfs_select.readfds, nfds);
943521fa314SDavid van Moolenbroek 	put_fd_set(proc, "writefds",
944521fa314SDavid van Moolenbroek 	    (vir_bytes)m_out->m_lc_vfs_select.writefds, nfds);
945521fa314SDavid van Moolenbroek 	put_fd_set(proc, "errorfds",
946521fa314SDavid van Moolenbroek 	    (vir_bytes)m_out->m_lc_vfs_select.errorfds, nfds);
947521fa314SDavid van Moolenbroek 	put_struct_timeval(proc, "timeout", 0, m_out->m_lc_vfs_select.timeout);
948521fa314SDavid van Moolenbroek 
949521fa314SDavid van Moolenbroek 	return CT_DONE;
950521fa314SDavid van Moolenbroek }
951521fa314SDavid van Moolenbroek 
952521fa314SDavid van Moolenbroek static void
vfs_select_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)953521fa314SDavid van Moolenbroek vfs_select_in(struct trace_proc * proc, const message * m_out,
954521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
955521fa314SDavid van Moolenbroek {
956521fa314SDavid van Moolenbroek 	vir_bytes readfds, writefds, errorfds;
957521fa314SDavid van Moolenbroek 	int nfds;
958521fa314SDavid van Moolenbroek 
959521fa314SDavid van Moolenbroek 	put_result(proc);
960521fa314SDavid van Moolenbroek 	if (failed)
961521fa314SDavid van Moolenbroek 		return;
962521fa314SDavid van Moolenbroek 
963521fa314SDavid van Moolenbroek 	nfds = m_out->m_lc_vfs_select.nfds;
964521fa314SDavid van Moolenbroek 
965521fa314SDavid van Moolenbroek 	readfds = (vir_bytes)m_out->m_lc_vfs_select.readfds;
966521fa314SDavid van Moolenbroek 	writefds = (vir_bytes)m_out->m_lc_vfs_select.writefds;
967521fa314SDavid van Moolenbroek 	errorfds = (vir_bytes)m_out->m_lc_vfs_select.errorfds;
968521fa314SDavid van Moolenbroek 
969521fa314SDavid van Moolenbroek 	if (readfds == 0 && writefds == 0 && errorfds == 0)
970521fa314SDavid van Moolenbroek 		return;
971521fa314SDavid van Moolenbroek 
972521fa314SDavid van Moolenbroek 	/* Omit names, because it looks weird. */
973521fa314SDavid van Moolenbroek 	put_open(proc, NULL, PF_NONAME, "(", ", ");
974521fa314SDavid van Moolenbroek 	if (readfds != 0)
975521fa314SDavid van Moolenbroek 		put_fd_set(proc, "readfds", readfds, nfds);
976521fa314SDavid van Moolenbroek 	if (writefds != 0)
977521fa314SDavid van Moolenbroek 		put_fd_set(proc, "writefds", writefds, nfds);
978521fa314SDavid van Moolenbroek 	if (errorfds != 0)
979521fa314SDavid van Moolenbroek 		put_fd_set(proc, "errorfds", errorfds, nfds);
980521fa314SDavid van Moolenbroek 	put_close(proc, ")");
981521fa314SDavid van Moolenbroek }
982521fa314SDavid van Moolenbroek 
983521fa314SDavid van Moolenbroek static int
vfs_fchdir_out(struct trace_proc * proc,const message * m_out)984521fa314SDavid van Moolenbroek vfs_fchdir_out(struct trace_proc * proc, const message * m_out)
985521fa314SDavid van Moolenbroek {
986521fa314SDavid van Moolenbroek 
987521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_fchdir.fd);
988521fa314SDavid van Moolenbroek 
989521fa314SDavid van Moolenbroek 	return CT_DONE;
990521fa314SDavid van Moolenbroek }
991521fa314SDavid van Moolenbroek 
992521fa314SDavid van Moolenbroek static int
vfs_fsync_out(struct trace_proc * proc,const message * m_out)993521fa314SDavid van Moolenbroek vfs_fsync_out(struct trace_proc * proc, const message * m_out)
994521fa314SDavid van Moolenbroek {
995521fa314SDavid van Moolenbroek 
996521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_fsync.fd);
997521fa314SDavid van Moolenbroek 
998521fa314SDavid van Moolenbroek 	return CT_DONE;
999521fa314SDavid van Moolenbroek }
1000521fa314SDavid van Moolenbroek 
1001521fa314SDavid van Moolenbroek static int
vfs_truncate_out(struct trace_proc * proc,const message * m_out)1002521fa314SDavid van Moolenbroek vfs_truncate_out(struct trace_proc * proc, const message * m_out)
1003521fa314SDavid van Moolenbroek {
1004521fa314SDavid van Moolenbroek 
1005521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_truncate.name,
1006521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_truncate.len);
1007521fa314SDavid van Moolenbroek 	put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset);
1008521fa314SDavid van Moolenbroek 
1009521fa314SDavid van Moolenbroek 	return CT_DONE;
1010521fa314SDavid van Moolenbroek }
1011521fa314SDavid van Moolenbroek 
1012521fa314SDavid van Moolenbroek static int
vfs_ftruncate_out(struct trace_proc * proc,const message * m_out)1013521fa314SDavid van Moolenbroek vfs_ftruncate_out(struct trace_proc * proc, const message * m_out)
1014521fa314SDavid van Moolenbroek {
1015521fa314SDavid van Moolenbroek 
1016521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_truncate.fd);
1017521fa314SDavid van Moolenbroek 	put_value(proc, "length", "%"PRId64, m_out->m_lc_vfs_truncate.offset);
1018521fa314SDavid van Moolenbroek 
1019521fa314SDavid van Moolenbroek 	return CT_DONE;
1020521fa314SDavid van Moolenbroek }
1021521fa314SDavid van Moolenbroek 
1022521fa314SDavid van Moolenbroek static int
vfs_fchmod_out(struct trace_proc * proc,const message * m_out)1023521fa314SDavid van Moolenbroek vfs_fchmod_out(struct trace_proc * proc, const message * m_out)
1024521fa314SDavid van Moolenbroek {
1025521fa314SDavid van Moolenbroek 
1026521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_fchmod.fd);
1027521fa314SDavid van Moolenbroek 	put_mode(proc, "mode", m_out->m_lc_vfs_fchmod.mode);
1028521fa314SDavid van Moolenbroek 
1029521fa314SDavid van Moolenbroek 	return CT_DONE;
1030521fa314SDavid van Moolenbroek }
1031521fa314SDavid van Moolenbroek 
1032521fa314SDavid van Moolenbroek static int
vfs_fchown_out(struct trace_proc * proc,const message * m_out)1033521fa314SDavid van Moolenbroek vfs_fchown_out(struct trace_proc * proc, const message * m_out)
1034521fa314SDavid van Moolenbroek {
1035521fa314SDavid van Moolenbroek 
1036521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_chown.fd);
1037521fa314SDavid van Moolenbroek 	/* -1 means "keep the current value" so print as signed */
1038521fa314SDavid van Moolenbroek 	put_value(proc, "owner", "%d", m_out->m_lc_vfs_chown.owner);
1039521fa314SDavid van Moolenbroek 	put_value(proc, "group", "%d", m_out->m_lc_vfs_chown.group);
1040521fa314SDavid van Moolenbroek 
1041521fa314SDavid van Moolenbroek 	return CT_DONE;
1042521fa314SDavid van Moolenbroek }
1043521fa314SDavid van Moolenbroek 
1044521fa314SDavid van Moolenbroek static const char *
vfs_utimens_name(const message * m_out)1045521fa314SDavid van Moolenbroek vfs_utimens_name(const message * m_out)
1046521fa314SDavid van Moolenbroek {
1047521fa314SDavid van Moolenbroek 	int has_path, has_flags;
1048521fa314SDavid van Moolenbroek 
1049521fa314SDavid van Moolenbroek 	has_path = (m_out->m_vfs_utimens.name != NULL);
1050521fa314SDavid van Moolenbroek 	has_flags = (m_out->m_vfs_utimens.flags != 0);
1051521fa314SDavid van Moolenbroek 
1052521fa314SDavid van Moolenbroek 	if (has_path && m_out->m_vfs_utimens.flags == AT_SYMLINK_NOFOLLOW)
1053521fa314SDavid van Moolenbroek 		return "lutimens";
1054521fa314SDavid van Moolenbroek 	if (has_path && !has_flags)
1055521fa314SDavid van Moolenbroek 		return "utimens";
1056521fa314SDavid van Moolenbroek 	else if (!has_path && !has_flags)
1057521fa314SDavid van Moolenbroek 		return "futimens";
1058521fa314SDavid van Moolenbroek 	else
1059521fa314SDavid van Moolenbroek 		return "utimensat";
1060521fa314SDavid van Moolenbroek }
1061521fa314SDavid van Moolenbroek 
1062521fa314SDavid van Moolenbroek static const struct flags at_flags[] = {
1063521fa314SDavid van Moolenbroek 	FLAG(AT_EACCESS),
1064521fa314SDavid van Moolenbroek 	FLAG(AT_SYMLINK_NOFOLLOW),
1065521fa314SDavid van Moolenbroek 	FLAG(AT_SYMLINK_FOLLOW),
1066521fa314SDavid van Moolenbroek 	FLAG(AT_REMOVEDIR),
1067521fa314SDavid van Moolenbroek };
1068521fa314SDavid van Moolenbroek 
1069521fa314SDavid van Moolenbroek static void
put_utimens_timespec(struct trace_proc * proc,const char * name,time_t sec,long nsec)1070521fa314SDavid van Moolenbroek put_utimens_timespec(struct trace_proc * proc, const char * name,
1071521fa314SDavid van Moolenbroek 	time_t sec, long nsec)
1072521fa314SDavid van Moolenbroek {
1073521fa314SDavid van Moolenbroek 
1074521fa314SDavid van Moolenbroek 	/* No field names. */
1075521fa314SDavid van Moolenbroek 	put_open(proc, name, PF_NONAME, "{", ", ");
1076521fa314SDavid van Moolenbroek 
1077521fa314SDavid van Moolenbroek 	put_time(proc, "tv_sec", sec);
1078521fa314SDavid van Moolenbroek 
1079521fa314SDavid van Moolenbroek 	if (!valuesonly && nsec == UTIME_NOW)
1080521fa314SDavid van Moolenbroek 		put_field(proc, "tv_nsec", "UTIME_NOW");
1081521fa314SDavid van Moolenbroek 	else if (!valuesonly && nsec == UTIME_OMIT)
1082521fa314SDavid van Moolenbroek 		put_field(proc, "tv_nsec", "UTIME_OMIT");
1083521fa314SDavid van Moolenbroek 	else
1084521fa314SDavid van Moolenbroek 		put_value(proc, "tv_nsec", "%ld", nsec);
1085521fa314SDavid van Moolenbroek 
1086521fa314SDavid van Moolenbroek 	put_close(proc, "}");
1087521fa314SDavid van Moolenbroek }
1088521fa314SDavid van Moolenbroek 
1089521fa314SDavid van Moolenbroek static int
vfs_utimens_out(struct trace_proc * proc,const message * m_out)1090521fa314SDavid van Moolenbroek vfs_utimens_out(struct trace_proc * proc, const message * m_out)
1091521fa314SDavid van Moolenbroek {
1092521fa314SDavid van Moolenbroek 	int has_path, has_flags;
1093521fa314SDavid van Moolenbroek 
1094521fa314SDavid van Moolenbroek 	/* Here we do not care about the utimens/lutimens distinction. */
1095521fa314SDavid van Moolenbroek 	has_path = (m_out->m_vfs_utimens.name != NULL);
1096521fa314SDavid van Moolenbroek 	has_flags = !!(m_out->m_vfs_utimens.flags & ~AT_SYMLINK_NOFOLLOW);
1097521fa314SDavid van Moolenbroek 
1098521fa314SDavid van Moolenbroek 	if (has_path && has_flags)
1099521fa314SDavid van Moolenbroek 		put_field(proc, "fd", "AT_CWD"); /* utimensat */
1100521fa314SDavid van Moolenbroek 	else if (!has_path)
1101521fa314SDavid van Moolenbroek 		put_fd(proc, "fd", m_out->m_vfs_utimens.fd); /* futimes */
1102521fa314SDavid van Moolenbroek 	if (has_path || has_flags) /* lutimes, utimes, utimensat */
1103521fa314SDavid van Moolenbroek 		put_buf(proc, "path", PF_PATH,
1104521fa314SDavid van Moolenbroek 		    (vir_bytes)m_out->m_vfs_utimens.name,
1105521fa314SDavid van Moolenbroek 		    m_out->m_vfs_utimens.len);
1106521fa314SDavid van Moolenbroek 
1107521fa314SDavid van Moolenbroek 	put_open(proc, "times", 0, "[", ", ");
1108521fa314SDavid van Moolenbroek 	put_utimens_timespec(proc, "atime", m_out->m_vfs_utimens.atime,
1109521fa314SDavid van Moolenbroek 	    m_out->m_vfs_utimens.ansec);
1110521fa314SDavid van Moolenbroek 	put_utimens_timespec(proc, "mtime", m_out->m_vfs_utimens.mtime,
1111521fa314SDavid van Moolenbroek 	    m_out->m_vfs_utimens.mnsec);
1112521fa314SDavid van Moolenbroek 	put_close(proc, "]");
1113521fa314SDavid van Moolenbroek 
1114521fa314SDavid van Moolenbroek 	if (has_flags)
1115521fa314SDavid van Moolenbroek 		put_flags(proc, "flag", at_flags, COUNT(at_flags), "0x%x",
1116521fa314SDavid van Moolenbroek 		    m_out->m_vfs_utimens.flags);
1117521fa314SDavid van Moolenbroek 
1118521fa314SDavid van Moolenbroek 	return CT_DONE;
1119521fa314SDavid van Moolenbroek }
1120521fa314SDavid van Moolenbroek 
1121521fa314SDavid van Moolenbroek static const struct flags statvfs_flags[] = {
1122521fa314SDavid van Moolenbroek 	FLAG(ST_WAIT),
1123521fa314SDavid van Moolenbroek 	FLAG(ST_NOWAIT),
1124521fa314SDavid van Moolenbroek };
1125521fa314SDavid van Moolenbroek 
1126521fa314SDavid van Moolenbroek static const struct flags st_flags[] = {
1127521fa314SDavid van Moolenbroek 	FLAG(ST_RDONLY),
1128521fa314SDavid van Moolenbroek 	FLAG(ST_SYNCHRONOUS),
1129521fa314SDavid van Moolenbroek 	FLAG(ST_NOEXEC),
1130521fa314SDavid van Moolenbroek 	FLAG(ST_NOSUID),
1131521fa314SDavid van Moolenbroek 	FLAG(ST_NODEV),
1132521fa314SDavid van Moolenbroek 	FLAG(ST_UNION),
1133521fa314SDavid van Moolenbroek 	FLAG(ST_ASYNC),
1134521fa314SDavid van Moolenbroek 	FLAG(ST_NOCOREDUMP),
1135521fa314SDavid van Moolenbroek 	FLAG(ST_RELATIME),
1136521fa314SDavid van Moolenbroek 	FLAG(ST_IGNORE),
1137521fa314SDavid van Moolenbroek 	FLAG(ST_NOATIME),
1138521fa314SDavid van Moolenbroek 	FLAG(ST_SYMPERM),
1139521fa314SDavid van Moolenbroek 	FLAG(ST_NODEVMTIME),
1140521fa314SDavid van Moolenbroek 	FLAG(ST_SOFTDEP),
1141521fa314SDavid van Moolenbroek 	FLAG(ST_LOG),
1142521fa314SDavid van Moolenbroek 	FLAG(ST_EXTATTR),
1143521fa314SDavid van Moolenbroek 	FLAG(ST_EXRDONLY),
1144521fa314SDavid van Moolenbroek 	FLAG(ST_EXPORTED),
1145521fa314SDavid van Moolenbroek 	FLAG(ST_DEFEXPORTED),
1146521fa314SDavid van Moolenbroek 	FLAG(ST_EXPORTANON),
1147521fa314SDavid van Moolenbroek 	FLAG(ST_EXKERB),
1148521fa314SDavid van Moolenbroek 	FLAG(ST_EXNORESPORT),
1149521fa314SDavid van Moolenbroek 	FLAG(ST_EXPUBLIC),
1150521fa314SDavid van Moolenbroek 	FLAG(ST_LOCAL),
1151521fa314SDavid van Moolenbroek 	FLAG(ST_QUOTA),
1152521fa314SDavid van Moolenbroek 	FLAG(ST_ROOTFS),
1153521fa314SDavid van Moolenbroek 	FLAG(ST_NOTRUNC),
1154521fa314SDavid van Moolenbroek };
1155521fa314SDavid van Moolenbroek 
1156521fa314SDavid van Moolenbroek static void
put_struct_statvfs(struct trace_proc * proc,const char * name,int flags,vir_bytes addr)1157521fa314SDavid van Moolenbroek put_struct_statvfs(struct trace_proc * proc, const char * name, int flags,
1158521fa314SDavid van Moolenbroek 	vir_bytes addr)
1159521fa314SDavid van Moolenbroek {
1160521fa314SDavid van Moolenbroek 	struct statvfs buf;
1161521fa314SDavid van Moolenbroek 
1162521fa314SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
1163521fa314SDavid van Moolenbroek 		return;
1164521fa314SDavid van Moolenbroek 
1165521fa314SDavid van Moolenbroek 	put_flags(proc, "f_flag", st_flags, COUNT(st_flags), "0x%x",
1166521fa314SDavid van Moolenbroek 	    buf.f_flag);
1167521fa314SDavid van Moolenbroek 	put_value(proc, "f_bsize", "%lu", buf.f_bsize);
1168521fa314SDavid van Moolenbroek 	if (verbose > 0 || buf.f_bsize != buf.f_frsize)
1169521fa314SDavid van Moolenbroek 		put_value(proc, "f_frsize", "%lu", buf.f_frsize);
1170521fa314SDavid van Moolenbroek 	if (verbose > 1)
1171521fa314SDavid van Moolenbroek 		put_value(proc, "f_iosize", "%lu", buf.f_iosize);
1172521fa314SDavid van Moolenbroek 
1173521fa314SDavid van Moolenbroek 	put_value(proc, "f_blocks", "%"PRIu64, buf.f_blocks);
1174521fa314SDavid van Moolenbroek 	put_value(proc, "f_bfree", "%"PRIu64, buf.f_bfree);
1175521fa314SDavid van Moolenbroek 	if (verbose > 1) {
1176521fa314SDavid van Moolenbroek 		put_value(proc, "f_bavail", "%"PRIu64, buf.f_bavail);
1177521fa314SDavid van Moolenbroek 		put_value(proc, "f_bresvd", "%"PRIu64, buf.f_bresvd);
1178521fa314SDavid van Moolenbroek 	}
1179521fa314SDavid van Moolenbroek 
1180521fa314SDavid van Moolenbroek 	if (verbose > 0) {
1181521fa314SDavid van Moolenbroek 		put_value(proc, "f_files", "%"PRIu64, buf.f_files);
1182521fa314SDavid van Moolenbroek 		put_value(proc, "f_ffree", "%"PRIu64, buf.f_ffree);
1183521fa314SDavid van Moolenbroek 	}
1184521fa314SDavid van Moolenbroek 	if (verbose > 1) {
1185521fa314SDavid van Moolenbroek 		put_value(proc, "f_favail", "%"PRIu64, buf.f_favail);
1186521fa314SDavid van Moolenbroek 		put_value(proc, "f_fresvd", "%"PRIu64, buf.f_fresvd);
1187521fa314SDavid van Moolenbroek 	}
1188521fa314SDavid van Moolenbroek 
1189521fa314SDavid van Moolenbroek 	if (verbose > 1) {
1190521fa314SDavid van Moolenbroek 		put_value(proc, "f_syncreads", "%"PRIu64, buf.f_syncreads);
1191521fa314SDavid van Moolenbroek 		put_value(proc, "f_syncwrites", "%"PRIu64, buf.f_syncwrites);
1192521fa314SDavid van Moolenbroek 		put_value(proc, "f_asyncreads", "%"PRIu64, buf.f_asyncreads);
1193521fa314SDavid van Moolenbroek 		put_value(proc, "f_asyncwrites", "%"PRIu64, buf.f_asyncwrites);
1194521fa314SDavid van Moolenbroek 
1195521fa314SDavid van Moolenbroek 		put_value(proc, "f_fsidx", "<%"PRId32",%"PRId32">",
1196521fa314SDavid van Moolenbroek 		    buf.f_fsidx.__fsid_val[0], buf.f_fsidx.__fsid_val[1]);
1197521fa314SDavid van Moolenbroek 	}
1198521fa314SDavid van Moolenbroek 	put_dev(proc, "f_fsid", buf.f_fsid); /* MINIX3 interpretation! */
1199521fa314SDavid van Moolenbroek 
1200521fa314SDavid van Moolenbroek 	if (verbose > 0)
1201521fa314SDavid van Moolenbroek 		put_value(proc, "f_namemax", "%lu", buf.f_namemax);
1202521fa314SDavid van Moolenbroek 	if (verbose > 1)
1203521fa314SDavid van Moolenbroek 		put_value(proc, "f_owner", "%u", buf.f_owner);
1204521fa314SDavid van Moolenbroek 
1205521fa314SDavid van Moolenbroek 	put_buf(proc, "f_fstypename", PF_STRING | PF_LOCADDR,
1206521fa314SDavid van Moolenbroek 	    (vir_bytes)&buf.f_fstypename, sizeof(buf.f_fstypename));
1207521fa314SDavid van Moolenbroek 	if (verbose > 0)
1208521fa314SDavid van Moolenbroek 		put_buf(proc, "f_mntfromname", PF_STRING | PF_LOCADDR,
1209521fa314SDavid van Moolenbroek 		    (vir_bytes)&buf.f_mntfromname, sizeof(buf.f_mntfromname));
1210521fa314SDavid van Moolenbroek 	put_buf(proc, "f_mntonname", PF_STRING | PF_LOCADDR,
1211521fa314SDavid van Moolenbroek 	    (vir_bytes)&buf.f_mntonname, sizeof(buf.f_mntonname));
1212521fa314SDavid van Moolenbroek 
1213521fa314SDavid van Moolenbroek 	put_close_struct(proc, verbose > 1);
1214521fa314SDavid van Moolenbroek }
1215521fa314SDavid van Moolenbroek 
1216521fa314SDavid van Moolenbroek static void
put_statvfs_array(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,int count)1217521fa314SDavid van Moolenbroek put_statvfs_array(struct trace_proc * proc, const char * name, int flags,
1218521fa314SDavid van Moolenbroek 	vir_bytes addr, int count)
1219521fa314SDavid van Moolenbroek {
1220521fa314SDavid van Moolenbroek 	struct statvfs buf;
1221521fa314SDavid van Moolenbroek 	int i, max;
1222521fa314SDavid van Moolenbroek 
1223c38dbb97SDavid van Moolenbroek 	if ((flags & PF_FAILED) || valuesonly > 1 || count < 0) {
1224521fa314SDavid van Moolenbroek 		put_ptr(proc, name, addr);
1225521fa314SDavid van Moolenbroek 
1226521fa314SDavid van Moolenbroek 		return;
1227521fa314SDavid van Moolenbroek 	}
1228521fa314SDavid van Moolenbroek 
1229521fa314SDavid van Moolenbroek 	if (count == 0) {
1230521fa314SDavid van Moolenbroek 		put_field(proc, name, "[]");
1231521fa314SDavid van Moolenbroek 
1232521fa314SDavid van Moolenbroek 		return;
1233521fa314SDavid van Moolenbroek 	}
1234521fa314SDavid van Moolenbroek 
1235521fa314SDavid van Moolenbroek 	if (verbose == 0)
1236521fa314SDavid van Moolenbroek 		max = 0;
1237521fa314SDavid van Moolenbroek 	else if (verbose == 1)
1238521fa314SDavid van Moolenbroek 		max = 1; /* TODO: is this reasonable? */
1239521fa314SDavid van Moolenbroek 	else
1240521fa314SDavid van Moolenbroek 		max = INT_MAX;
1241521fa314SDavid van Moolenbroek 
1242521fa314SDavid van Moolenbroek 	if (max > count)
1243521fa314SDavid van Moolenbroek 		max = count;
1244521fa314SDavid van Moolenbroek 
1245521fa314SDavid van Moolenbroek 	for (i = 0; i < max; i++) {
1246521fa314SDavid van Moolenbroek 		if (mem_get_data(proc->pid, addr + i * sizeof(buf), &buf,
1247521fa314SDavid van Moolenbroek 		    sizeof(buf)) < 0) {
1248521fa314SDavid van Moolenbroek 			if (i == 0) {
1249521fa314SDavid van Moolenbroek 				put_ptr(proc, name, addr);
1250521fa314SDavid van Moolenbroek 
1251521fa314SDavid van Moolenbroek 				return;
1252521fa314SDavid van Moolenbroek 			}
1253521fa314SDavid van Moolenbroek 
1254521fa314SDavid van Moolenbroek 			break;
1255521fa314SDavid van Moolenbroek 		}
1256521fa314SDavid van Moolenbroek 
1257521fa314SDavid van Moolenbroek 		if (i == 0)
1258521fa314SDavid van Moolenbroek 			put_open(proc, name, PF_NONAME, "[", ", ");
1259521fa314SDavid van Moolenbroek 
1260521fa314SDavid van Moolenbroek 		put_struct_statvfs(proc, NULL, PF_LOCADDR, (vir_bytes)&buf);
1261521fa314SDavid van Moolenbroek 	}
1262521fa314SDavid van Moolenbroek 
1263521fa314SDavid van Moolenbroek 	if (i == 0)
1264521fa314SDavid van Moolenbroek 		put_open(proc, name, PF_NONAME, "[", ", ");
1265521fa314SDavid van Moolenbroek 	if (i < max)
1266521fa314SDavid van Moolenbroek 		put_tail(proc, 0, 0);
1267521fa314SDavid van Moolenbroek 	else if (count > i)
1268521fa314SDavid van Moolenbroek 		put_tail(proc, count, i);
1269521fa314SDavid van Moolenbroek 	put_close(proc, "]");
1270521fa314SDavid van Moolenbroek }
1271521fa314SDavid van Moolenbroek 
1272521fa314SDavid van Moolenbroek static int
vfs_getvfsstat_out(struct trace_proc * proc,const message * m_out)1273521fa314SDavid van Moolenbroek vfs_getvfsstat_out(struct trace_proc * proc, const message * m_out)
1274521fa314SDavid van Moolenbroek {
1275521fa314SDavid van Moolenbroek 
1276521fa314SDavid van Moolenbroek 	if (m_out->m_lc_vfs_getvfsstat.buf == 0) {
1277521fa314SDavid van Moolenbroek 		put_ptr(proc, "buf", m_out->m_lc_vfs_getvfsstat.buf);
1278521fa314SDavid van Moolenbroek 		put_value(proc, "bufsize", "%zu",
1279521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_getvfsstat.len);
1280521fa314SDavid van Moolenbroek 		put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags),
1281521fa314SDavid van Moolenbroek 		    "%d", m_out->m_lc_vfs_getvfsstat.flags);
1282521fa314SDavid van Moolenbroek 		return CT_DONE;
1283521fa314SDavid van Moolenbroek 	} else
1284521fa314SDavid van Moolenbroek 		return CT_NOTDONE;
1285521fa314SDavid van Moolenbroek }
1286521fa314SDavid van Moolenbroek 
1287521fa314SDavid van Moolenbroek static void
vfs_getvfsstat_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)1288521fa314SDavid van Moolenbroek vfs_getvfsstat_in(struct trace_proc * proc, const message * m_out,
1289521fa314SDavid van Moolenbroek 	const message * m_in, int failed)
1290521fa314SDavid van Moolenbroek {
1291521fa314SDavid van Moolenbroek 
1292521fa314SDavid van Moolenbroek 	if (m_out->m_lc_vfs_getvfsstat.buf != 0) {
1293521fa314SDavid van Moolenbroek 		put_statvfs_array(proc, "buf", failed,
1294521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_getvfsstat.buf, m_in->m_type);
1295521fa314SDavid van Moolenbroek 		put_value(proc, "bufsize", "%zu",
1296521fa314SDavid van Moolenbroek 		    m_out->m_lc_vfs_getvfsstat.len);
1297521fa314SDavid van Moolenbroek 		put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags),
1298521fa314SDavid van Moolenbroek 		    "%d", m_out->m_lc_vfs_getvfsstat.flags);
1299521fa314SDavid van Moolenbroek 		put_equals(proc);
1300521fa314SDavid van Moolenbroek 	}
1301521fa314SDavid van Moolenbroek 	put_result(proc);
1302521fa314SDavid van Moolenbroek }
1303521fa314SDavid van Moolenbroek 
1304521fa314SDavid van Moolenbroek static int
vfs_statvfs1_out(struct trace_proc * proc,const message * m_out)1305521fa314SDavid van Moolenbroek vfs_statvfs1_out(struct trace_proc * proc, const message * m_out)
1306521fa314SDavid van Moolenbroek {
1307521fa314SDavid van Moolenbroek 
1308521fa314SDavid van Moolenbroek 	put_buf(proc, "path", PF_PATH, m_out->m_lc_vfs_statvfs1.name,
1309521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_statvfs1.len);
1310521fa314SDavid van Moolenbroek 
1311521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
1312521fa314SDavid van Moolenbroek }
1313521fa314SDavid van Moolenbroek 
1314521fa314SDavid van Moolenbroek static void
vfs_statvfs1_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)1315521fa314SDavid van Moolenbroek vfs_statvfs1_in(struct trace_proc * proc, const message * m_out,
1316521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
1317521fa314SDavid van Moolenbroek {
1318521fa314SDavid van Moolenbroek 
1319521fa314SDavid van Moolenbroek 	put_struct_statvfs(proc, "buf", failed, m_out->m_lc_vfs_statvfs1.buf);
1320521fa314SDavid van Moolenbroek 	put_flags(proc, "flags", statvfs_flags, COUNT(statvfs_flags), "%d",
1321521fa314SDavid van Moolenbroek 	    m_out->m_lc_vfs_statvfs1.flags);
1322521fa314SDavid van Moolenbroek 	put_equals(proc);
1323521fa314SDavid van Moolenbroek 	put_result(proc);
1324521fa314SDavid van Moolenbroek }
1325521fa314SDavid van Moolenbroek 
1326521fa314SDavid van Moolenbroek /* This function is shared between statvfs1 and fstatvfs1. */
1327521fa314SDavid van Moolenbroek static int
vfs_fstatvfs1_out(struct trace_proc * proc,const message * m_out)1328521fa314SDavid van Moolenbroek vfs_fstatvfs1_out(struct trace_proc * proc, const message * m_out)
1329521fa314SDavid van Moolenbroek {
1330521fa314SDavid van Moolenbroek 
1331521fa314SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_statvfs1.fd);
1332521fa314SDavid van Moolenbroek 
1333521fa314SDavid van Moolenbroek 	return CT_NOTDONE;
1334521fa314SDavid van Moolenbroek }
1335521fa314SDavid van Moolenbroek 
1336521fa314SDavid van Moolenbroek static int
vfs_svrctl_out(struct trace_proc * proc,const message * m_out)1337521fa314SDavid van Moolenbroek vfs_svrctl_out(struct trace_proc * proc, const message * m_out)
1338521fa314SDavid van Moolenbroek {
1339521fa314SDavid van Moolenbroek 
1340521fa314SDavid van Moolenbroek 	put_ioctl_req(proc, "request", m_out->m_lc_svrctl.request,
1341521fa314SDavid van Moolenbroek 	    TRUE /*is_svrctl*/);
1342521fa314SDavid van Moolenbroek 	return put_ioctl_arg_out(proc, "arg", m_out->m_lc_svrctl.request,
1343521fa314SDavid van Moolenbroek 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1344521fa314SDavid van Moolenbroek }
1345521fa314SDavid van Moolenbroek 
1346521fa314SDavid van Moolenbroek static void
vfs_svrctl_in(struct trace_proc * proc,const message * m_out,const message * __unused m_in,int failed)1347521fa314SDavid van Moolenbroek vfs_svrctl_in(struct trace_proc * proc, const message * m_out,
1348521fa314SDavid van Moolenbroek 	const message * __unused m_in, int failed)
1349521fa314SDavid van Moolenbroek {
1350521fa314SDavid van Moolenbroek 
1351521fa314SDavid van Moolenbroek 	put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_svrctl.request,
1352521fa314SDavid van Moolenbroek 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1353521fa314SDavid van Moolenbroek }
1354521fa314SDavid van Moolenbroek 
1355521fa314SDavid van Moolenbroek static int
vfs_gcov_flush_out(struct trace_proc * proc,const message * m_out)1356521fa314SDavid van Moolenbroek vfs_gcov_flush_out(struct trace_proc * proc, const message * m_out)
1357521fa314SDavid van Moolenbroek {
1358521fa314SDavid van Moolenbroek 
13593ac58492SDavid van Moolenbroek 	put_buf(proc, "label", PF_STRING, m_out->m_lc_vfs_gcov.label,
13603ac58492SDavid van Moolenbroek 	    m_out->m_lc_vfs_gcov.labellen);
13613ac58492SDavid van Moolenbroek 	put_ptr(proc, "buff", m_out->m_lc_vfs_gcov.buf);
13623ac58492SDavid van Moolenbroek 	put_value(proc, "buff_sz", "%zu", m_out->m_lc_vfs_gcov.buflen);
1363521fa314SDavid van Moolenbroek 
1364521fa314SDavid van Moolenbroek 	return CT_DONE;
1365521fa314SDavid van Moolenbroek }
1366521fa314SDavid van Moolenbroek 
1367c38dbb97SDavid van Moolenbroek void
put_socket_family(struct trace_proc * proc,const char * name,int family)1368c38dbb97SDavid van Moolenbroek put_socket_family(struct trace_proc * proc, const char * name, int family)
1369c38dbb97SDavid van Moolenbroek {
1370c38dbb97SDavid van Moolenbroek 	const char *text = NULL;
1371c38dbb97SDavid van Moolenbroek 
1372c38dbb97SDavid van Moolenbroek 	if (!valuesonly) {
1373c38dbb97SDavid van Moolenbroek 		/*
1374c38dbb97SDavid van Moolenbroek 		 * For socket(2) and socketpair(2) this should really be using
1375c38dbb97SDavid van Moolenbroek 		 * the prefix "PF_" since those functions take a protocol
1376c38dbb97SDavid van Moolenbroek 		 * family rather than an address family.  This rule is applied
1377c38dbb97SDavid van Moolenbroek 		 * fairly consistently within the system.  Here I caved because
1378c38dbb97SDavid van Moolenbroek 		 * I don't want to duplicate this entire function just for the
1379c38dbb97SDavid van Moolenbroek 		 * one letter.  There are exceptions however; some names only
1380c38dbb97SDavid van Moolenbroek 		 * exist as "PF_".
1381c38dbb97SDavid van Moolenbroek 		 */
1382c38dbb97SDavid van Moolenbroek 		switch (family) {
1383c38dbb97SDavid van Moolenbroek 		TEXT(AF_UNSPEC);
1384c38dbb97SDavid van Moolenbroek 		TEXT(AF_LOCAL);
1385c38dbb97SDavid van Moolenbroek 		TEXT(AF_INET);
1386c38dbb97SDavid van Moolenbroek 		TEXT(AF_IMPLINK);
1387c38dbb97SDavid van Moolenbroek 		TEXT(AF_PUP);
1388c38dbb97SDavid van Moolenbroek 		TEXT(AF_CHAOS);
1389c38dbb97SDavid van Moolenbroek 		TEXT(AF_NS);
1390c38dbb97SDavid van Moolenbroek 		TEXT(AF_ISO);
1391c38dbb97SDavid van Moolenbroek 		TEXT(AF_ECMA);
1392c38dbb97SDavid van Moolenbroek 		TEXT(AF_DATAKIT);
1393c38dbb97SDavid van Moolenbroek 		TEXT(AF_CCITT);
1394c38dbb97SDavid van Moolenbroek 		TEXT(AF_SNA);
1395c38dbb97SDavid van Moolenbroek 		TEXT(AF_DECnet);
1396c38dbb97SDavid van Moolenbroek 		TEXT(AF_DLI);
1397c38dbb97SDavid van Moolenbroek 		TEXT(AF_LAT);
1398c38dbb97SDavid van Moolenbroek 		TEXT(AF_HYLINK);
1399c38dbb97SDavid van Moolenbroek 		TEXT(AF_APPLETALK);
1400c38dbb97SDavid van Moolenbroek 		TEXT(AF_OROUTE);
1401c38dbb97SDavid van Moolenbroek 		TEXT(AF_LINK);
1402c38dbb97SDavid van Moolenbroek 		TEXT(PF_XTP);
1403c38dbb97SDavid van Moolenbroek 		TEXT(AF_COIP);
1404c38dbb97SDavid van Moolenbroek 		TEXT(AF_CNT);
1405c38dbb97SDavid van Moolenbroek 		TEXT(PF_RTIP);
1406c38dbb97SDavid van Moolenbroek 		TEXT(AF_IPX);
1407c38dbb97SDavid van Moolenbroek 		TEXT(AF_INET6);
1408c38dbb97SDavid van Moolenbroek 		TEXT(PF_PIP);
1409c38dbb97SDavid van Moolenbroek 		TEXT(AF_ISDN);
1410c38dbb97SDavid van Moolenbroek 		TEXT(AF_NATM);
1411c38dbb97SDavid van Moolenbroek 		TEXT(AF_ARP);
1412c38dbb97SDavid van Moolenbroek 		TEXT(PF_KEY);
1413c38dbb97SDavid van Moolenbroek 		TEXT(AF_BLUETOOTH);
1414c38dbb97SDavid van Moolenbroek 		TEXT(AF_IEEE80211);
1415c38dbb97SDavid van Moolenbroek 		TEXT(AF_MPLS);
1416c38dbb97SDavid van Moolenbroek 		TEXT(AF_ROUTE);
1417c38dbb97SDavid van Moolenbroek 		}
1418c38dbb97SDavid van Moolenbroek 	}
1419c38dbb97SDavid van Moolenbroek 
1420c38dbb97SDavid van Moolenbroek 	if (text != NULL)
1421c38dbb97SDavid van Moolenbroek 		put_field(proc, name, text);
1422c38dbb97SDavid van Moolenbroek 	else
1423c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "%d", family);
1424c38dbb97SDavid van Moolenbroek }
1425c38dbb97SDavid van Moolenbroek 
1426c38dbb97SDavid van Moolenbroek static const struct flags socket_types[] = {
1427c38dbb97SDavid van Moolenbroek 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_STREAM),
1428c38dbb97SDavid van Moolenbroek 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_DGRAM),
1429c38dbb97SDavid van Moolenbroek 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RAW),
1430c38dbb97SDavid van Moolenbroek 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RDM),
1431c38dbb97SDavid van Moolenbroek 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_SEQPACKET),
1432c38dbb97SDavid van Moolenbroek 	FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_CONN_DGRAM),
1433c38dbb97SDavid van Moolenbroek 	FLAG(SOCK_CLOEXEC),
1434c38dbb97SDavid van Moolenbroek 	FLAG(SOCK_NONBLOCK),
1435c38dbb97SDavid van Moolenbroek 	FLAG(SOCK_NOSIGPIPE),
1436c38dbb97SDavid van Moolenbroek };
1437c38dbb97SDavid van Moolenbroek 
1438c38dbb97SDavid van Moolenbroek void
put_socket_type(struct trace_proc * proc,const char * name,int type)1439c38dbb97SDavid van Moolenbroek put_socket_type(struct trace_proc * proc, const char * name, int type)
1440c38dbb97SDavid van Moolenbroek {
1441c38dbb97SDavid van Moolenbroek 
1442c38dbb97SDavid van Moolenbroek 	put_flags(proc, name, socket_types, COUNT(socket_types), "%d", type);
1443c38dbb97SDavid van Moolenbroek }
1444c38dbb97SDavid van Moolenbroek 
1445c38dbb97SDavid van Moolenbroek static void
put_socket_protocol(struct trace_proc * proc,const char * name,int family,int type,int protocol)1446c38dbb97SDavid van Moolenbroek put_socket_protocol(struct trace_proc * proc, const char * name, int family,
1447c38dbb97SDavid van Moolenbroek 	int type, int protocol)
1448c38dbb97SDavid van Moolenbroek {
1449c38dbb97SDavid van Moolenbroek 	const char *text = NULL;
1450c38dbb97SDavid van Moolenbroek 
1451c38dbb97SDavid van Moolenbroek 	if (!valuesonly && (type == SOCK_RAW || protocol != 0)) {
1452c38dbb97SDavid van Moolenbroek 		switch (family) {
1453c38dbb97SDavid van Moolenbroek 		case PF_INET:
1454c38dbb97SDavid van Moolenbroek 		case PF_INET6:
1455c38dbb97SDavid van Moolenbroek 			/* TODO: is this all that is used in socket(2)? */
1456c38dbb97SDavid van Moolenbroek 			switch (protocol) {
1457c38dbb97SDavid van Moolenbroek 			TEXT(IPPROTO_IP);
1458c38dbb97SDavid van Moolenbroek 			TEXT(IPPROTO_ICMP);
1459c38dbb97SDavid van Moolenbroek 			TEXT(IPPROTO_IGMP);
1460c38dbb97SDavid van Moolenbroek 			TEXT(IPPROTO_TCP);
1461c38dbb97SDavid van Moolenbroek 			TEXT(IPPROTO_UDP);
1462c38dbb97SDavid van Moolenbroek 			TEXT(IPPROTO_ICMPV6);
1463c38dbb97SDavid van Moolenbroek 			TEXT(IPPROTO_RAW);
1464c38dbb97SDavid van Moolenbroek 			}
1465c38dbb97SDavid van Moolenbroek 			break;
1466c38dbb97SDavid van Moolenbroek #if 0 /* not yet */
1467c38dbb97SDavid van Moolenbroek 		case PF_BLUETOOTH:
1468c38dbb97SDavid van Moolenbroek 			switch (protocol) {
1469c38dbb97SDavid van Moolenbroek 			TEXT(BTPROTO_HCI);
1470c38dbb97SDavid van Moolenbroek 			TEXT(BTPROTO_L2CAP);
1471c38dbb97SDavid van Moolenbroek 			TEXT(BTPROTO_RFCOMM);
1472c38dbb97SDavid van Moolenbroek 			TEXT(BTPROTO_SCO);
1473c38dbb97SDavid van Moolenbroek 			}
1474c38dbb97SDavid van Moolenbroek 			break;
1475c38dbb97SDavid van Moolenbroek #endif
1476c38dbb97SDavid van Moolenbroek 		}
1477c38dbb97SDavid van Moolenbroek 	}
1478c38dbb97SDavid van Moolenbroek 
1479c38dbb97SDavid van Moolenbroek 	if (text != NULL)
1480c38dbb97SDavid van Moolenbroek 		put_field(proc, name, text);
1481c38dbb97SDavid van Moolenbroek 	else
1482c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "%d", protocol);
1483c38dbb97SDavid van Moolenbroek }
1484c38dbb97SDavid van Moolenbroek 
1485c38dbb97SDavid van Moolenbroek static int
vfs_socket_out(struct trace_proc * proc,const message * m_out)1486c38dbb97SDavid van Moolenbroek vfs_socket_out(struct trace_proc * proc, const message * m_out)
1487c38dbb97SDavid van Moolenbroek {
1488c38dbb97SDavid van Moolenbroek 
1489c38dbb97SDavid van Moolenbroek 	put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain);
1490c38dbb97SDavid van Moolenbroek 	put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type);
1491c38dbb97SDavid van Moolenbroek 	put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain,
1492c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK,
1493c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_socket.protocol);
1494c38dbb97SDavid van Moolenbroek 
1495c38dbb97SDavid van Moolenbroek 	return CT_DONE;
1496c38dbb97SDavid van Moolenbroek }
1497c38dbb97SDavid van Moolenbroek 
1498c38dbb97SDavid van Moolenbroek static int
vfs_socketpair_out(struct trace_proc * proc,const message * m_out)1499c38dbb97SDavid van Moolenbroek vfs_socketpair_out(struct trace_proc * proc, const message * m_out)
1500c38dbb97SDavid van Moolenbroek {
1501c38dbb97SDavid van Moolenbroek 
1502c38dbb97SDavid van Moolenbroek 	put_socket_family(proc, "domain", m_out->m_lc_vfs_socket.domain);
1503c38dbb97SDavid van Moolenbroek 	put_socket_type(proc, "type", m_out->m_lc_vfs_socket.type);
1504c38dbb97SDavid van Moolenbroek 	put_socket_protocol(proc, "protocol", m_out->m_lc_vfs_socket.domain,
1505c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_socket.type & ~SOCK_FLAGS_MASK,
1506c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_socket.protocol);
1507c38dbb97SDavid van Moolenbroek 
1508c38dbb97SDavid van Moolenbroek 	return CT_NOTDONE;
1509c38dbb97SDavid van Moolenbroek }
1510c38dbb97SDavid van Moolenbroek 
1511c38dbb97SDavid van Moolenbroek static void
vfs_socketpair_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)1512c38dbb97SDavid van Moolenbroek vfs_socketpair_in(struct trace_proc * proc, const message * m_out,
1513c38dbb97SDavid van Moolenbroek 	const message * m_in, int failed)
1514c38dbb97SDavid van Moolenbroek {
1515c38dbb97SDavid van Moolenbroek 
1516c38dbb97SDavid van Moolenbroek 	if (!failed) {
1517c38dbb97SDavid van Moolenbroek 		put_open(proc, "fd", PF_NONAME, "[", ", ");
1518c38dbb97SDavid van Moolenbroek 		put_fd(proc, "fd0", m_in->m_vfs_lc_fdpair.fd0);
1519c38dbb97SDavid van Moolenbroek 		put_fd(proc, "fd1", m_in->m_vfs_lc_fdpair.fd1);
1520c38dbb97SDavid van Moolenbroek 		put_close(proc, "]");
1521c38dbb97SDavid van Moolenbroek 	} else
1522c38dbb97SDavid van Moolenbroek 		put_field(proc, "fd", "&..");
1523c38dbb97SDavid van Moolenbroek 	put_equals(proc);
1524c38dbb97SDavid van Moolenbroek 	put_result(proc);
1525c38dbb97SDavid van Moolenbroek }
1526c38dbb97SDavid van Moolenbroek 
1527c38dbb97SDavid van Moolenbroek void
put_in_addr(struct trace_proc * proc,const char * name,struct in_addr in)1528c38dbb97SDavid van Moolenbroek put_in_addr(struct trace_proc * proc, const char * name, struct in_addr in)
1529c38dbb97SDavid van Moolenbroek {
1530c38dbb97SDavid van Moolenbroek 
1531c38dbb97SDavid van Moolenbroek 	if (!valuesonly) {
1532c38dbb97SDavid van Moolenbroek 		/* Is this an acceptable encapsulation? */
1533c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "[%s]", inet_ntoa(in));
1534c38dbb97SDavid van Moolenbroek 	} else
1535c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "0x%08x", ntohl(in.s_addr));
1536c38dbb97SDavid van Moolenbroek }
1537c38dbb97SDavid van Moolenbroek 
1538c38dbb97SDavid van Moolenbroek static void
put_in6_addr(struct trace_proc * proc,const char * name,struct in6_addr * in)1539c38dbb97SDavid van Moolenbroek put_in6_addr(struct trace_proc * proc, const char * name, struct in6_addr * in)
1540c38dbb97SDavid van Moolenbroek {
1541c38dbb97SDavid van Moolenbroek 	char buf[INET6_ADDRSTRLEN];
1542c38dbb97SDavid van Moolenbroek 	const char *ptr;
1543c38dbb97SDavid van Moolenbroek 	unsigned int i, n;
1544c38dbb97SDavid van Moolenbroek 
1545c38dbb97SDavid van Moolenbroek 	if (!valuesonly &&
1546c38dbb97SDavid van Moolenbroek 	    (ptr = inet_ntop(AF_INET6, in, buf, sizeof(buf))) != NULL) {
1547c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "[%s]", ptr);
1548c38dbb97SDavid van Moolenbroek 	} else {
1549c38dbb97SDavid van Moolenbroek 		for (i = n = 0; i < 16; i++)
1550c38dbb97SDavid van Moolenbroek 			n += snprintf(buf + n, sizeof(buf) - n, "%02x",
1551c38dbb97SDavid van Moolenbroek 			    ((unsigned char *)in)[i]);
1552c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "0x%s", buf);
1553c38dbb97SDavid van Moolenbroek 	}
1554c38dbb97SDavid van Moolenbroek }
1555c38dbb97SDavid van Moolenbroek 
1556c38dbb97SDavid van Moolenbroek static void
put_struct_sockaddr(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,socklen_t addr_len)1557c38dbb97SDavid van Moolenbroek put_struct_sockaddr(struct trace_proc * proc, const char * name, int flags,
1558c38dbb97SDavid van Moolenbroek 	vir_bytes addr, socklen_t addr_len)
1559c38dbb97SDavid van Moolenbroek {
1560c38dbb97SDavid van Moolenbroek 	char buf[UCHAR_MAX + 1];
1561c38dbb97SDavid van Moolenbroek 	uint8_t len;
1562c38dbb97SDavid van Moolenbroek 	sa_family_t family;
1563c38dbb97SDavid van Moolenbroek 	struct sockaddr sa;
1564c38dbb97SDavid van Moolenbroek 	struct sockaddr_in sin;
1565c38dbb97SDavid van Moolenbroek 	struct sockaddr_in6 sin6;
1566c38dbb97SDavid van Moolenbroek 	int all, off, left;
1567c38dbb97SDavid van Moolenbroek 
1568c38dbb97SDavid van Moolenbroek 	/*
1569c38dbb97SDavid van Moolenbroek 	 * For UNIX domain sockets, make sure there's always room to add a
1570c38dbb97SDavid van Moolenbroek 	 * trailing NULL byte, because UDS paths are not necessarily null
1571c38dbb97SDavid van Moolenbroek 	 * terminated.
1572c38dbb97SDavid van Moolenbroek 	 */
1573c38dbb97SDavid van Moolenbroek 	if (addr_len < offsetof(struct sockaddr, sa_data) ||
1574c38dbb97SDavid van Moolenbroek 	    addr_len >= sizeof(buf)) {
1575c38dbb97SDavid van Moolenbroek 		put_ptr(proc, name, addr);
1576c38dbb97SDavid van Moolenbroek 
1577c38dbb97SDavid van Moolenbroek 		return;
1578c38dbb97SDavid van Moolenbroek 	}
1579c38dbb97SDavid van Moolenbroek 
1580c38dbb97SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, buf, addr_len))
1581c38dbb97SDavid van Moolenbroek 		return;
1582c38dbb97SDavid van Moolenbroek 
1583c38dbb97SDavid van Moolenbroek 	memcpy(&sa, buf, sizeof(sa));
1584c38dbb97SDavid van Moolenbroek 	len = sa.sa_len;
1585c38dbb97SDavid van Moolenbroek 	family = sa.sa_family;
1586c38dbb97SDavid van Moolenbroek 	all = (verbose > 1);
1587c38dbb97SDavid van Moolenbroek 
1588c38dbb97SDavid van Moolenbroek 	switch (family) {
1589c38dbb97SDavid van Moolenbroek 	case AF_LOCAL:
1590c38dbb97SDavid van Moolenbroek 		if (verbose > 1)
1591c38dbb97SDavid van Moolenbroek 			put_value(proc, "sun_len", "%u", len);
1592c38dbb97SDavid van Moolenbroek 		if (verbose > 0)
1593c38dbb97SDavid van Moolenbroek 			put_socket_family(proc, "sun_family", family);
1594c38dbb97SDavid van Moolenbroek 		off = (int)offsetof(struct sockaddr_un, sun_path);
1595c38dbb97SDavid van Moolenbroek 		left = addr_len - off;
1596c38dbb97SDavid van Moolenbroek 		if (left > 0) {
1597c38dbb97SDavid van Moolenbroek 			buf[addr_len] = 0; /* force null termination */
1598c38dbb97SDavid van Moolenbroek 			put_buf(proc, "sun_path", PF_LOCADDR | PF_PATH,
1599c38dbb97SDavid van Moolenbroek 			    (vir_bytes)&buf[off],
1600c38dbb97SDavid van Moolenbroek 			    left + 1 /* include null byte */);
1601c38dbb97SDavid van Moolenbroek 		}
1602c38dbb97SDavid van Moolenbroek 		break;
1603c38dbb97SDavid van Moolenbroek 	case AF_INET:
1604c38dbb97SDavid van Moolenbroek 		if (verbose > 1)
1605c38dbb97SDavid van Moolenbroek 			put_value(proc, "sin_len", "%u", len);
1606c38dbb97SDavid van Moolenbroek 		if (verbose > 0)
1607c38dbb97SDavid van Moolenbroek 			put_socket_family(proc, "sin_family", family);
1608c38dbb97SDavid van Moolenbroek 		if (addr_len == sizeof(sin)) {
1609c38dbb97SDavid van Moolenbroek 			memcpy(&sin, buf, sizeof(sin));
1610c38dbb97SDavid van Moolenbroek 			put_value(proc, "sin_port", "%u", ntohs(sin.sin_port));
1611c38dbb97SDavid van Moolenbroek 			put_in_addr(proc, "sin_addr", sin.sin_addr);
1612c38dbb97SDavid van Moolenbroek 		} else
1613c38dbb97SDavid van Moolenbroek 			all = FALSE;
1614c38dbb97SDavid van Moolenbroek 		break;
1615c38dbb97SDavid van Moolenbroek 	case AF_INET6:
1616c38dbb97SDavid van Moolenbroek 		if (verbose > 1)
1617c38dbb97SDavid van Moolenbroek 			put_value(proc, "sin6_len", "%u", len);
1618c38dbb97SDavid van Moolenbroek 		if (verbose > 0)
1619c38dbb97SDavid van Moolenbroek 			put_socket_family(proc, "sin6_family", family);
1620c38dbb97SDavid van Moolenbroek 		if (addr_len == sizeof(sin6)) {
1621c38dbb97SDavid van Moolenbroek 			memcpy(&sin6, buf, sizeof(sin6));
1622c38dbb97SDavid van Moolenbroek 			put_value(proc, "sin6_port", "%u",
1623c38dbb97SDavid van Moolenbroek 			    ntohs(sin6.sin6_port));
1624c38dbb97SDavid van Moolenbroek 			if (verbose > 1)
1625c38dbb97SDavid van Moolenbroek 				put_value(proc, "sin6_flowinfo", "%"PRIu32,
1626c38dbb97SDavid van Moolenbroek 				    sin6.sin6_flowinfo);
1627c38dbb97SDavid van Moolenbroek 			put_in6_addr(proc, "sin6_addr", &sin6.sin6_addr);
1628c38dbb97SDavid van Moolenbroek 			if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
162940dec70cSDavid van Moolenbroek 			    IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
163040dec70cSDavid van Moolenbroek 			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) ||
1631c38dbb97SDavid van Moolenbroek 			    verbose > 0)
1632c38dbb97SDavid van Moolenbroek 				put_value(proc, "sin6_scope_id", "%"PRIu32,
1633c38dbb97SDavid van Moolenbroek 				    sin6.sin6_scope_id);
1634c38dbb97SDavid van Moolenbroek 		} else
1635c38dbb97SDavid van Moolenbroek 			all = FALSE;
1636c38dbb97SDavid van Moolenbroek 		break;
1637c38dbb97SDavid van Moolenbroek 	/* TODO: support for other address families */
1638c38dbb97SDavid van Moolenbroek 	default:
1639c38dbb97SDavid van Moolenbroek 		if (verbose > 1)
1640c38dbb97SDavid van Moolenbroek 			put_value(proc, "sa_len", "%u", len);
1641c38dbb97SDavid van Moolenbroek 		put_socket_family(proc, "sa_family", family);
1642c38dbb97SDavid van Moolenbroek 		all = (verbose > 1 && family == AF_UNSPEC);
1643c38dbb97SDavid van Moolenbroek 	}
1644c38dbb97SDavid van Moolenbroek 
1645c38dbb97SDavid van Moolenbroek 	put_close_struct(proc, all);
1646c38dbb97SDavid van Moolenbroek }
1647c38dbb97SDavid van Moolenbroek 
1648c38dbb97SDavid van Moolenbroek /* This function is shared between bind and connect. */
1649c38dbb97SDavid van Moolenbroek static int
vfs_bind_out(struct trace_proc * proc,const message * m_out)1650c38dbb97SDavid van Moolenbroek vfs_bind_out(struct trace_proc * proc, const message * m_out)
1651c38dbb97SDavid van Moolenbroek {
1652c38dbb97SDavid van Moolenbroek 
1653c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
1654c38dbb97SDavid van Moolenbroek 	put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sockaddr.addr,
1655c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockaddr.addr_len);
1656c38dbb97SDavid van Moolenbroek 	put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sockaddr.addr_len);
1657c38dbb97SDavid van Moolenbroek 
1658c38dbb97SDavid van Moolenbroek 	return CT_DONE;
1659c38dbb97SDavid van Moolenbroek }
1660c38dbb97SDavid van Moolenbroek 
1661c38dbb97SDavid van Moolenbroek static int
vfs_listen_out(struct trace_proc * proc,const message * m_out)1662c38dbb97SDavid van Moolenbroek vfs_listen_out(struct trace_proc * proc, const message * m_out)
1663c38dbb97SDavid van Moolenbroek {
1664c38dbb97SDavid van Moolenbroek 
1665c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_listen.fd);
1666c38dbb97SDavid van Moolenbroek 	put_value(proc, "backlog", "%d", m_out->m_lc_vfs_listen.backlog);
1667c38dbb97SDavid van Moolenbroek 
1668c38dbb97SDavid van Moolenbroek 	return CT_DONE;
1669c38dbb97SDavid van Moolenbroek }
1670c38dbb97SDavid van Moolenbroek 
1671c38dbb97SDavid van Moolenbroek static int
vfs_accept_out(struct trace_proc * proc,const message * m_out)1672c38dbb97SDavid van Moolenbroek vfs_accept_out(struct trace_proc * proc, const message * m_out)
1673c38dbb97SDavid van Moolenbroek {
1674c38dbb97SDavid van Moolenbroek 
1675c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
1676c38dbb97SDavid van Moolenbroek 
1677c38dbb97SDavid van Moolenbroek 	return CT_NOTDONE;
1678c38dbb97SDavid van Moolenbroek }
1679c38dbb97SDavid van Moolenbroek 
1680c38dbb97SDavid van Moolenbroek static void
vfs_accept_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)1681c38dbb97SDavid van Moolenbroek vfs_accept_in(struct trace_proc * proc, const message * m_out,
1682c38dbb97SDavid van Moolenbroek 	const message * m_in, int failed)
1683c38dbb97SDavid van Moolenbroek {
1684c38dbb97SDavid van Moolenbroek 
1685c38dbb97SDavid van Moolenbroek 	put_struct_sockaddr(proc, "addr", failed,
1686c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockaddr.addr, m_in->m_vfs_lc_socklen.len);
1687c38dbb97SDavid van Moolenbroek 	/*
1688c38dbb97SDavid van Moolenbroek 	 * We print the resulting address length rather than the given buffer
1689c38dbb97SDavid van Moolenbroek 	 * size here, as we do in recvfrom, getsockname, getpeername, and (less
1690c38dbb97SDavid van Moolenbroek 	 * explicitly) recvmsg.  We could also print both, by adding the
1691c38dbb97SDavid van Moolenbroek 	 * resulting length after the call result.
1692c38dbb97SDavid van Moolenbroek 	 */
1693c38dbb97SDavid van Moolenbroek 	if (m_out->m_lc_vfs_sockaddr.addr == 0)
1694c38dbb97SDavid van Moolenbroek 		put_field(proc, "addr_len", "NULL");
1695c38dbb97SDavid van Moolenbroek 	else if (!failed)
1696c38dbb97SDavid van Moolenbroek 		put_value(proc, "addr_len", "{%u}",
1697c38dbb97SDavid van Moolenbroek 		    m_in->m_vfs_lc_socklen.len);
1698c38dbb97SDavid van Moolenbroek 	else
1699c38dbb97SDavid van Moolenbroek 		put_field(proc, "addr_len", "&..");
1700c38dbb97SDavid van Moolenbroek 
1701c38dbb97SDavid van Moolenbroek 	put_equals(proc);
1702c38dbb97SDavid van Moolenbroek 	put_result(proc);
1703c38dbb97SDavid van Moolenbroek }
1704c38dbb97SDavid van Moolenbroek 
1705c38dbb97SDavid van Moolenbroek static const struct flags msg_flags[] = {
1706c38dbb97SDavid van Moolenbroek 	FLAG(MSG_OOB),
1707c38dbb97SDavid van Moolenbroek 	FLAG(MSG_PEEK),
1708c38dbb97SDavid van Moolenbroek 	FLAG(MSG_DONTROUTE),
1709c38dbb97SDavid van Moolenbroek 	FLAG(MSG_EOR),
1710c38dbb97SDavid van Moolenbroek 	FLAG(MSG_TRUNC),
1711c38dbb97SDavid van Moolenbroek 	FLAG(MSG_CTRUNC),
1712c38dbb97SDavid van Moolenbroek 	FLAG(MSG_WAITALL),
1713c38dbb97SDavid van Moolenbroek 	FLAG(MSG_DONTWAIT),
1714c38dbb97SDavid van Moolenbroek 	FLAG(MSG_BCAST),
1715c38dbb97SDavid van Moolenbroek 	FLAG(MSG_MCAST),
1716c38dbb97SDavid van Moolenbroek #ifdef MSG_NOSIGNAL
1717c38dbb97SDavid van Moolenbroek 	FLAG(MSG_NOSIGNAL),
1718c38dbb97SDavid van Moolenbroek #endif
1719c38dbb97SDavid van Moolenbroek 	FLAG(MSG_CMSG_CLOEXEC),
1720c38dbb97SDavid van Moolenbroek 	FLAG(MSG_NBIO),
1721c38dbb97SDavid van Moolenbroek 	FLAG(MSG_WAITFORONE),
1722c38dbb97SDavid van Moolenbroek };
1723c38dbb97SDavid van Moolenbroek 
1724c38dbb97SDavid van Moolenbroek static int
vfs_sendto_out(struct trace_proc * proc,const message * m_out)1725c38dbb97SDavid van Moolenbroek vfs_sendto_out(struct trace_proc * proc, const message * m_out)
1726c38dbb97SDavid van Moolenbroek {
1727c38dbb97SDavid van Moolenbroek 
1728c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd);
1729c38dbb97SDavid van Moolenbroek 	put_buf(proc, "buf", 0, m_out->m_lc_vfs_sendrecv.buf,
1730c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_readwrite.len);
1731c38dbb97SDavid van Moolenbroek 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len);
1732c38dbb97SDavid van Moolenbroek 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
1733c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sendrecv.flags);
1734c38dbb97SDavid van Moolenbroek 	put_struct_sockaddr(proc, "addr", 0, m_out->m_lc_vfs_sendrecv.addr,
1735c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sendrecv.addr_len);
1736c38dbb97SDavid van Moolenbroek 	put_value(proc, "addr_len", "%u", m_out->m_lc_vfs_sendrecv.addr_len);
1737c38dbb97SDavid van Moolenbroek 
1738c38dbb97SDavid van Moolenbroek 	return CT_DONE;
1739c38dbb97SDavid van Moolenbroek }
1740c38dbb97SDavid van Moolenbroek 
1741c38dbb97SDavid van Moolenbroek static void
put_struct_iovec(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,int len,ssize_t bmax)1742c38dbb97SDavid van Moolenbroek put_struct_iovec(struct trace_proc * proc, const char * name, int flags,
1743c38dbb97SDavid van Moolenbroek 	vir_bytes addr, int len, ssize_t bmax)
1744c38dbb97SDavid van Moolenbroek {
1745c38dbb97SDavid van Moolenbroek 	struct iovec iov;
1746c38dbb97SDavid van Moolenbroek 	size_t bytes;
1747c38dbb97SDavid van Moolenbroek 	int i, imax;
1748c38dbb97SDavid van Moolenbroek 
1749c38dbb97SDavid van Moolenbroek 	/*
1750c38dbb97SDavid van Moolenbroek 	 * For simplicity and clarity reasons, we currently print the I/O
1751c38dbb97SDavid van Moolenbroek 	 * vector as an array of data elements rather than an array of
1752c38dbb97SDavid van Moolenbroek 	 * structures.  We also copy in each element separately, because as of
1753c38dbb97SDavid van Moolenbroek 	 * writing there is no system support for more than one element anyway.
1754c38dbb97SDavid van Moolenbroek 	 * All of this may be changed later.
1755c38dbb97SDavid van Moolenbroek 	 */
1756c38dbb97SDavid van Moolenbroek 	if ((flags & PF_FAILED) || valuesonly > 1 || addr == 0 || len < 0) {
1757c38dbb97SDavid van Moolenbroek 		put_ptr(proc, name, addr);
1758c38dbb97SDavid van Moolenbroek 
1759c38dbb97SDavid van Moolenbroek 		return;
1760c38dbb97SDavid van Moolenbroek 	}
1761c38dbb97SDavid van Moolenbroek 
1762c38dbb97SDavid van Moolenbroek 	if (len == 0 || bmax == 0) {
1763c38dbb97SDavid van Moolenbroek 		put_field(proc, name, "[]");
1764c38dbb97SDavid van Moolenbroek 
1765c38dbb97SDavid van Moolenbroek 		return;
1766c38dbb97SDavid van Moolenbroek 	}
1767c38dbb97SDavid van Moolenbroek 
1768c38dbb97SDavid van Moolenbroek 	/* As per logic below, 'imax' must be set to a nonzero value here. */
1769c38dbb97SDavid van Moolenbroek 	if (verbose == 0)
1770c38dbb97SDavid van Moolenbroek 		imax = 4;
1771c38dbb97SDavid van Moolenbroek 	else if (verbose == 1)
1772c38dbb97SDavid van Moolenbroek 		imax = 16;
1773c38dbb97SDavid van Moolenbroek 	else
1774c38dbb97SDavid van Moolenbroek 		imax = INT_MAX;
1775c38dbb97SDavid van Moolenbroek 
1776c38dbb97SDavid van Moolenbroek 	for (i = 0; i < len && bmax > 0; i++) {
1777c38dbb97SDavid van Moolenbroek 		if (mem_get_data(proc->pid, addr, &iov, sizeof(iov)) < 0) {
1778c38dbb97SDavid van Moolenbroek 			if (i == 0) {
1779c38dbb97SDavid van Moolenbroek 				put_ptr(proc, name, addr);
1780c38dbb97SDavid van Moolenbroek 
1781c38dbb97SDavid van Moolenbroek 				return;
1782c38dbb97SDavid van Moolenbroek 			}
1783c38dbb97SDavid van Moolenbroek 
1784c38dbb97SDavid van Moolenbroek 			len = imax = 0; /* make put_tail() print an error */
1785c38dbb97SDavid van Moolenbroek 			break;
1786c38dbb97SDavid van Moolenbroek 		}
1787c38dbb97SDavid van Moolenbroek 
1788c38dbb97SDavid van Moolenbroek 		if (i == 0)
1789c38dbb97SDavid van Moolenbroek 			put_open(proc, name, 0, "[", ", ");
1790c38dbb97SDavid van Moolenbroek 
1791c38dbb97SDavid van Moolenbroek 		bytes = MIN(iov.iov_len, (size_t)bmax);
1792c38dbb97SDavid van Moolenbroek 
1793c38dbb97SDavid van Moolenbroek 		if (len < imax)
1794c38dbb97SDavid van Moolenbroek 			put_buf(proc, NULL, 0, (vir_bytes)iov.iov_base, bytes);
1795c38dbb97SDavid van Moolenbroek 
1796c38dbb97SDavid van Moolenbroek 		addr += sizeof(struct iovec);
1797c38dbb97SDavid van Moolenbroek 		bmax -= bytes;
1798c38dbb97SDavid van Moolenbroek 	}
1799c38dbb97SDavid van Moolenbroek 
1800c38dbb97SDavid van Moolenbroek 	if (imax == 0 || imax < len)
1801c38dbb97SDavid van Moolenbroek 		put_tail(proc, len, imax);
1802c38dbb97SDavid van Moolenbroek 	put_close(proc, "]");
1803c38dbb97SDavid van Moolenbroek }
1804c38dbb97SDavid van Moolenbroek 
1805*27852ebeSDavid van Moolenbroek static void
put_struct_sockcred(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,size_t left)1806*27852ebeSDavid van Moolenbroek put_struct_sockcred(struct trace_proc * proc, const char * name, int flags,
1807*27852ebeSDavid van Moolenbroek 	vir_bytes addr, size_t left)
1808c38dbb97SDavid van Moolenbroek {
1809*27852ebeSDavid van Moolenbroek 	struct sockcred sc;
1810c38dbb97SDavid van Moolenbroek 
1811*27852ebeSDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &sc, sizeof(sc)))
1812c38dbb97SDavid van Moolenbroek 		return;
1813c38dbb97SDavid van Moolenbroek 
1814*27852ebeSDavid van Moolenbroek 	put_value(proc, "sc_uid", "%u", sc.sc_uid);
1815*27852ebeSDavid van Moolenbroek 	if (verbose > 0)
1816*27852ebeSDavid van Moolenbroek 		put_value(proc, "sc_euid", "%u", sc.sc_euid);
1817*27852ebeSDavid van Moolenbroek 	put_value(proc, "sc_gid", "%u", sc.sc_gid);
1818c38dbb97SDavid van Moolenbroek 	if (verbose > 0) {
1819*27852ebeSDavid van Moolenbroek 		put_value(proc, "sc_egid", "%u", sc.sc_egid);
1820c38dbb97SDavid van Moolenbroek 		if (verbose > 1)
1821*27852ebeSDavid van Moolenbroek 			put_value(proc, "sc_ngroups", "%d", sc.sc_ngroups);
1822*27852ebeSDavid van Moolenbroek 		if (left >= sizeof(sc.sc_groups[0]) * (sc.sc_ngroups - 1)) {
1823*27852ebeSDavid van Moolenbroek 			put_groups(proc, "sc_groups", flags,
1824*27852ebeSDavid van Moolenbroek 			    addr + offsetof(struct sockcred, sc_groups),
1825*27852ebeSDavid van Moolenbroek 			    sc.sc_ngroups);
1826*27852ebeSDavid van Moolenbroek 		} else
1827*27852ebeSDavid van Moolenbroek 			put_field(proc, "sc_groups", "..");
1828c38dbb97SDavid van Moolenbroek 	}
1829c38dbb97SDavid van Moolenbroek 
1830*27852ebeSDavid van Moolenbroek 	put_close_struct(proc, verbose > 1);
1831c38dbb97SDavid van Moolenbroek }
1832c38dbb97SDavid van Moolenbroek 
1833c38dbb97SDavid van Moolenbroek static void
put_socket_level(struct trace_proc * proc,const char * name,int level)1834c38dbb97SDavid van Moolenbroek put_socket_level(struct trace_proc * proc, const char * name, int level)
1835c38dbb97SDavid van Moolenbroek {
1836c38dbb97SDavid van Moolenbroek 
1837c38dbb97SDavid van Moolenbroek 	/*
1838c38dbb97SDavid van Moolenbroek 	 * Unfortunately, the level is a domain-specific protocol number.  That
1839c38dbb97SDavid van Moolenbroek 	 * means that without knowing how the socket was created, we cannot
1840c38dbb97SDavid van Moolenbroek 	 * tell what it means.  The only thing we can print is SOL_SOCKET,
1841c38dbb97SDavid van Moolenbroek 	 * which is the same across all domains.
1842c38dbb97SDavid van Moolenbroek 	 */
1843c38dbb97SDavid van Moolenbroek 	if (!valuesonly && level == SOL_SOCKET)
1844c38dbb97SDavid van Moolenbroek 		put_field(proc, name, "SOL_SOCKET");
1845c38dbb97SDavid van Moolenbroek 	else
1846c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "%d", level);
1847c38dbb97SDavid van Moolenbroek }
1848c38dbb97SDavid van Moolenbroek 
1849c38dbb97SDavid van Moolenbroek void
put_cmsg_type(struct trace_proc * proc,const char * name,int type)1850c38dbb97SDavid van Moolenbroek put_cmsg_type(struct trace_proc * proc, const char * name, int type)
1851c38dbb97SDavid van Moolenbroek {
1852c38dbb97SDavid van Moolenbroek 	const char *text = NULL;
1853c38dbb97SDavid van Moolenbroek 
1854c38dbb97SDavid van Moolenbroek 	if (!valuesonly) {
1855c38dbb97SDavid van Moolenbroek 		switch (type) {
1856c38dbb97SDavid van Moolenbroek 		TEXT(SCM_RIGHTS);
1857c38dbb97SDavid van Moolenbroek 		TEXT(SCM_CREDS);
1858c38dbb97SDavid van Moolenbroek 		TEXT(SCM_TIMESTAMP);
1859c38dbb97SDavid van Moolenbroek 		}
1860c38dbb97SDavid van Moolenbroek 	}
1861c38dbb97SDavid van Moolenbroek 
1862c38dbb97SDavid van Moolenbroek 	if (text != NULL)
1863c38dbb97SDavid van Moolenbroek 		put_field(proc, name, text);
1864c38dbb97SDavid van Moolenbroek 	else
1865c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "%d", type);
1866c38dbb97SDavid van Moolenbroek }
1867c38dbb97SDavid van Moolenbroek 
1868c38dbb97SDavid van Moolenbroek static void
put_cmsg_rights(struct trace_proc * proc,const char * name,char * buf,size_t size,char * cptr,size_t chunk,vir_bytes addr,size_t len)1869c38dbb97SDavid van Moolenbroek put_cmsg_rights(struct trace_proc * proc, const char * name, char * buf,
1870c38dbb97SDavid van Moolenbroek 	size_t size, char * cptr, size_t chunk, vir_bytes addr, size_t len)
1871c38dbb97SDavid van Moolenbroek {
1872c38dbb97SDavid van Moolenbroek 	unsigned int i, nfds;
1873c38dbb97SDavid van Moolenbroek 	int *ptr;
1874c38dbb97SDavid van Moolenbroek 
1875c38dbb97SDavid van Moolenbroek 	put_open(proc, name, PF_NONAME, "[", ", ");
1876c38dbb97SDavid van Moolenbroek 
1877c38dbb97SDavid van Moolenbroek 	/*
1878c38dbb97SDavid van Moolenbroek 	 * Since file descriptors are important, we print them all, regardless
1879c38dbb97SDavid van Moolenbroek 	 * of the current verbosity level.  Start with the file descriptors
1880c38dbb97SDavid van Moolenbroek 	 * that are already copied into the local buffer.
1881c38dbb97SDavid van Moolenbroek 	 */
1882c38dbb97SDavid van Moolenbroek 	ptr = (int *)cptr;
1883c38dbb97SDavid van Moolenbroek 	chunk = MIN(chunk, len);
1884c38dbb97SDavid van Moolenbroek 
1885c38dbb97SDavid van Moolenbroek 	nfds = chunk / sizeof(int);
1886c38dbb97SDavid van Moolenbroek 	for (i = 0; i < nfds; i++)
1887c38dbb97SDavid van Moolenbroek 		put_fd(proc, NULL, ptr[i]);
1888c38dbb97SDavid van Moolenbroek 
1889c38dbb97SDavid van Moolenbroek 	/* Then do the remaining file descriptors, in chunks. */
1890c38dbb97SDavid van Moolenbroek 	size -= size % sizeof(int);
1891c38dbb97SDavid van Moolenbroek 
1892c38dbb97SDavid van Moolenbroek 	for (len -= chunk; len >= sizeof(int); len -= chunk) {
1893c38dbb97SDavid van Moolenbroek 		chunk = MIN(len, size);
1894c38dbb97SDavid van Moolenbroek 
1895c38dbb97SDavid van Moolenbroek 		if (mem_get_data(proc->pid, addr, buf, chunk) < 0) {
1896c38dbb97SDavid van Moolenbroek 			put_field(proc, NULL, "..");
1897c38dbb97SDavid van Moolenbroek 
1898c38dbb97SDavid van Moolenbroek 			break;
1899c38dbb97SDavid van Moolenbroek 		}
1900c38dbb97SDavid van Moolenbroek 
1901c38dbb97SDavid van Moolenbroek 		ptr = (int *)buf;
1902c38dbb97SDavid van Moolenbroek 		nfds = chunk / sizeof(int);
1903c38dbb97SDavid van Moolenbroek 		for (i = 0; i < nfds; i++)
1904c38dbb97SDavid van Moolenbroek 			put_fd(proc, NULL, ptr[i]);
1905c38dbb97SDavid van Moolenbroek 
1906c38dbb97SDavid van Moolenbroek 		addr += chunk;
1907c38dbb97SDavid van Moolenbroek 	}
1908c38dbb97SDavid van Moolenbroek 
1909c38dbb97SDavid van Moolenbroek 	put_close(proc, "]");
1910c38dbb97SDavid van Moolenbroek }
1911c38dbb97SDavid van Moolenbroek 
1912c38dbb97SDavid van Moolenbroek static void
put_cmsg(struct trace_proc * proc,const char * name,vir_bytes addr,size_t len)1913c38dbb97SDavid van Moolenbroek put_cmsg(struct trace_proc * proc, const char * name, vir_bytes addr,
1914c38dbb97SDavid van Moolenbroek 	size_t len)
1915c38dbb97SDavid van Moolenbroek {
1916c38dbb97SDavid van Moolenbroek 	struct cmsghdr cmsg;
1917*27852ebeSDavid van Moolenbroek 	char buf[CMSG_SPACE(sizeof(struct sockcred))];
1918c38dbb97SDavid van Moolenbroek 	size_t off, chunk, datalen;
1919c38dbb97SDavid van Moolenbroek 
1920c38dbb97SDavid van Moolenbroek 	if (valuesonly > 1 || addr == 0 || len < CMSG_LEN(0)) {
1921c38dbb97SDavid van Moolenbroek 		put_ptr(proc, name, addr);
1922c38dbb97SDavid van Moolenbroek 
1923c38dbb97SDavid van Moolenbroek 		return;
1924c38dbb97SDavid van Moolenbroek 	}
1925c38dbb97SDavid van Moolenbroek 
1926c38dbb97SDavid van Moolenbroek 	for (off = 0; off < len; off += CMSG_SPACE(datalen)) {
1927c38dbb97SDavid van Moolenbroek 		chunk = MIN(len - off, sizeof(buf));
1928c38dbb97SDavid van Moolenbroek 
1929c38dbb97SDavid van Moolenbroek 		if (chunk < CMSG_LEN(0))
1930c38dbb97SDavid van Moolenbroek 			break;
1931c38dbb97SDavid van Moolenbroek 
1932c38dbb97SDavid van Moolenbroek 		if (mem_get_data(proc->pid, addr + off, buf, chunk) < 0) {
1933c38dbb97SDavid van Moolenbroek 			if (off == 0) {
1934c38dbb97SDavid van Moolenbroek 				put_ptr(proc, name, addr);
1935c38dbb97SDavid van Moolenbroek 
1936c38dbb97SDavid van Moolenbroek 				return;
1937c38dbb97SDavid van Moolenbroek 			}
1938c38dbb97SDavid van Moolenbroek 			break;
1939c38dbb97SDavid van Moolenbroek 		}
1940c38dbb97SDavid van Moolenbroek 
1941c38dbb97SDavid van Moolenbroek 		if (off == 0)
1942c38dbb97SDavid van Moolenbroek 			put_open(proc, name, 0, "[", ", ");
1943c38dbb97SDavid van Moolenbroek 
1944c38dbb97SDavid van Moolenbroek 		memcpy(&cmsg, buf, sizeof(cmsg));
1945c38dbb97SDavid van Moolenbroek 
1946c38dbb97SDavid van Moolenbroek 		put_open(proc, NULL, 0, "{", ", ");
1947c38dbb97SDavid van Moolenbroek 		if (verbose > 0)
1948c38dbb97SDavid van Moolenbroek 			put_value(proc, "cmsg_len", "%u", cmsg.cmsg_len);
1949c38dbb97SDavid van Moolenbroek 		put_socket_level(proc, "cmsg_level", cmsg.cmsg_level);
1950c38dbb97SDavid van Moolenbroek 		if (cmsg.cmsg_level == SOL_SOCKET)
1951c38dbb97SDavid van Moolenbroek 			put_cmsg_type(proc, "cmsg_type", cmsg.cmsg_type);
1952c38dbb97SDavid van Moolenbroek 		else
1953c38dbb97SDavid van Moolenbroek 			put_value(proc, "cmsg_type", "%d", cmsg.cmsg_type);
1954c38dbb97SDavid van Moolenbroek 
1955c38dbb97SDavid van Moolenbroek 		if (cmsg.cmsg_len < CMSG_LEN(0) || off + cmsg.cmsg_len > len) {
1956c38dbb97SDavid van Moolenbroek 			put_tail(proc, 0, 0);
1957c38dbb97SDavid van Moolenbroek 			put_close(proc, "}");
1958c38dbb97SDavid van Moolenbroek 			break;
1959c38dbb97SDavid van Moolenbroek 		}
1960c38dbb97SDavid van Moolenbroek 
1961c38dbb97SDavid van Moolenbroek 		datalen = cmsg.cmsg_len - CMSG_LEN(0);
1962c38dbb97SDavid van Moolenbroek 
1963c38dbb97SDavid van Moolenbroek 		if (cmsg.cmsg_level == SOL_SOCKET &&
1964c38dbb97SDavid van Moolenbroek 		    cmsg.cmsg_type == SCM_RIGHTS) {
1965c38dbb97SDavid van Moolenbroek 			put_cmsg_rights(proc, "cmsg_data", buf, sizeof(buf),
1966c38dbb97SDavid van Moolenbroek 			    &buf[CMSG_LEN(0)], chunk - CMSG_LEN(0),
1967c38dbb97SDavid van Moolenbroek 			    addr + off + chunk, datalen);
1968c38dbb97SDavid van Moolenbroek 		} else if (cmsg.cmsg_level == SOL_SOCKET &&
1969c38dbb97SDavid van Moolenbroek 		    cmsg.cmsg_type == SCM_CREDS &&
1970*27852ebeSDavid van Moolenbroek 		    datalen >= sizeof(struct sockcred) &&
1971c38dbb97SDavid van Moolenbroek 		    chunk >= CMSG_LEN(datalen)) {
1972*27852ebeSDavid van Moolenbroek 			put_struct_sockcred(proc, "cmsg_data", PF_LOCADDR,
1973*27852ebeSDavid van Moolenbroek 			    (vir_bytes)&buf[CMSG_LEN(0)],
1974*27852ebeSDavid van Moolenbroek 			    datalen - sizeof(struct sockcred));
1975c38dbb97SDavid van Moolenbroek 		} else if (datalen > 0)
1976c38dbb97SDavid van Moolenbroek 			put_field(proc, "cmsg_data", "..");
1977c38dbb97SDavid van Moolenbroek 
1978c38dbb97SDavid van Moolenbroek 		if (verbose == 0)
1979c38dbb97SDavid van Moolenbroek 			put_field(proc, NULL, "..");
1980c38dbb97SDavid van Moolenbroek 		put_close(proc, "}");
1981c38dbb97SDavid van Moolenbroek 	}
1982c38dbb97SDavid van Moolenbroek 
1983c38dbb97SDavid van Moolenbroek 	if (off < len)
1984c38dbb97SDavid van Moolenbroek 		put_field(proc, NULL, "..");
1985c38dbb97SDavid van Moolenbroek 	put_close(proc, "]");
1986c38dbb97SDavid van Moolenbroek }
1987c38dbb97SDavid van Moolenbroek 
1988c38dbb97SDavid van Moolenbroek static void
put_struct_msghdr(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,ssize_t max)1989c38dbb97SDavid van Moolenbroek put_struct_msghdr(struct trace_proc * proc, const char * name, int flags,
1990c38dbb97SDavid van Moolenbroek 	vir_bytes addr, ssize_t max)
1991c38dbb97SDavid van Moolenbroek {
1992c38dbb97SDavid van Moolenbroek 	struct msghdr msg;
1993c38dbb97SDavid van Moolenbroek 	int all;
1994c38dbb97SDavid van Moolenbroek 
1995c38dbb97SDavid van Moolenbroek 	if (!put_open_struct(proc, name, flags, addr, &msg, sizeof(msg)))
1996c38dbb97SDavid van Moolenbroek 		return;
1997c38dbb97SDavid van Moolenbroek 
1998c38dbb97SDavid van Moolenbroek 	all = TRUE;
1999c38dbb97SDavid van Moolenbroek 
2000c38dbb97SDavid van Moolenbroek 	if (msg.msg_name != NULL || verbose > 1) {
2001c38dbb97SDavid van Moolenbroek 		put_struct_sockaddr(proc, "msg_name", 0,
2002c38dbb97SDavid van Moolenbroek 		    (vir_bytes)msg.msg_name, msg.msg_namelen);
2003c38dbb97SDavid van Moolenbroek 		if (verbose > 0)
2004c38dbb97SDavid van Moolenbroek 			put_value(proc, "msg_namelen", "%u", msg.msg_namelen);
2005c38dbb97SDavid van Moolenbroek 		else
2006c38dbb97SDavid van Moolenbroek 			all = FALSE;
2007c38dbb97SDavid van Moolenbroek 	} else
2008c38dbb97SDavid van Moolenbroek 		all = FALSE;
2009c38dbb97SDavid van Moolenbroek 
2010c38dbb97SDavid van Moolenbroek 	put_struct_iovec(proc, "msg_iov", 0, (vir_bytes)msg.msg_iov,
2011c38dbb97SDavid van Moolenbroek 	    msg.msg_iovlen, max);
2012c38dbb97SDavid van Moolenbroek 	if (verbose > 0)
2013c38dbb97SDavid van Moolenbroek 		put_value(proc, "msg_iovlen", "%d", msg.msg_iovlen);
2014c38dbb97SDavid van Moolenbroek 	else
2015c38dbb97SDavid van Moolenbroek 		all = FALSE;
2016c38dbb97SDavid van Moolenbroek 
2017c38dbb97SDavid van Moolenbroek 	if (msg.msg_control != NULL || verbose > 1) {
2018c38dbb97SDavid van Moolenbroek 		put_cmsg(proc, "msg_control", (vir_bytes)msg.msg_control,
2019c38dbb97SDavid van Moolenbroek 		    msg.msg_controllen);
2020c38dbb97SDavid van Moolenbroek 
2021c38dbb97SDavid van Moolenbroek 		if (verbose > 0)
2022c38dbb97SDavid van Moolenbroek 			put_value(proc, "msg_controllen", "%u",
2023c38dbb97SDavid van Moolenbroek 			    msg.msg_controllen);
2024c38dbb97SDavid van Moolenbroek 		else
2025c38dbb97SDavid van Moolenbroek 			all = FALSE;
2026c38dbb97SDavid van Moolenbroek 	} else
2027c38dbb97SDavid van Moolenbroek 		all = FALSE;
2028c38dbb97SDavid van Moolenbroek 
2029c38dbb97SDavid van Moolenbroek 	/* When receiving, print the flags field as well. */
2030c38dbb97SDavid van Moolenbroek 	if (flags & PF_ALT)
2031c38dbb97SDavid van Moolenbroek 		put_flags(proc, "msg_flags", msg_flags, COUNT(msg_flags),
2032c38dbb97SDavid van Moolenbroek 		    "0x%x", msg.msg_flags);
2033c38dbb97SDavid van Moolenbroek 
2034c38dbb97SDavid van Moolenbroek 	put_close_struct(proc, all);
2035c38dbb97SDavid van Moolenbroek }
2036c38dbb97SDavid van Moolenbroek 
2037c38dbb97SDavid van Moolenbroek static int
vfs_sendmsg_out(struct trace_proc * proc,const message * m_out)2038c38dbb97SDavid van Moolenbroek vfs_sendmsg_out(struct trace_proc * proc, const message * m_out)
2039c38dbb97SDavid van Moolenbroek {
2040c38dbb97SDavid van Moolenbroek 
2041c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sockmsg.fd);
2042c38dbb97SDavid van Moolenbroek 	put_struct_msghdr(proc, "msg", 0, m_out->m_lc_vfs_sockmsg.msgbuf,
2043c38dbb97SDavid van Moolenbroek 	    SSIZE_MAX);
2044c38dbb97SDavid van Moolenbroek 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
2045c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockmsg.flags);
2046c38dbb97SDavid van Moolenbroek 
2047c38dbb97SDavid van Moolenbroek 	return CT_DONE;
2048c38dbb97SDavid van Moolenbroek }
2049c38dbb97SDavid van Moolenbroek 
2050c38dbb97SDavid van Moolenbroek static int
vfs_recvfrom_out(struct trace_proc * proc,const message * m_out)2051c38dbb97SDavid van Moolenbroek vfs_recvfrom_out(struct trace_proc * proc, const message * m_out)
2052c38dbb97SDavid van Moolenbroek {
2053c38dbb97SDavid van Moolenbroek 
2054c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sendrecv.fd);
2055c38dbb97SDavid van Moolenbroek 
2056c38dbb97SDavid van Moolenbroek 	return CT_NOTDONE;
2057c38dbb97SDavid van Moolenbroek }
2058c38dbb97SDavid van Moolenbroek 
2059c38dbb97SDavid van Moolenbroek static void
vfs_recvfrom_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)2060c38dbb97SDavid van Moolenbroek vfs_recvfrom_in(struct trace_proc * proc, const message * m_out,
2061c38dbb97SDavid van Moolenbroek 	const message * m_in, int failed)
2062c38dbb97SDavid van Moolenbroek {
2063c38dbb97SDavid van Moolenbroek 
2064c38dbb97SDavid van Moolenbroek 	put_buf(proc, "buf", failed, m_out->m_lc_vfs_sendrecv.buf,
2065c38dbb97SDavid van Moolenbroek 	    m_in->m_type);
2066c38dbb97SDavid van Moolenbroek 	put_value(proc, "len", "%zu", m_out->m_lc_vfs_sendrecv.len);
2067c38dbb97SDavid van Moolenbroek 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
2068c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sendrecv.flags);
2069c38dbb97SDavid van Moolenbroek 	put_struct_sockaddr(proc, "addr", failed,
2070c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sendrecv.addr, m_in->m_vfs_lc_socklen.len);
2071c38dbb97SDavid van Moolenbroek 	if (m_out->m_lc_vfs_sendrecv.addr == 0)
2072c38dbb97SDavid van Moolenbroek 		put_field(proc, "addr_len", "NULL");
2073c38dbb97SDavid van Moolenbroek 	else if (!failed)
2074c38dbb97SDavid van Moolenbroek 		put_value(proc, "addr_len", "{%u}",
2075c38dbb97SDavid van Moolenbroek 		    m_in->m_vfs_lc_socklen.len);
2076c38dbb97SDavid van Moolenbroek 	else
2077c38dbb97SDavid van Moolenbroek 		put_field(proc, "addr_len", "&..");
2078c38dbb97SDavid van Moolenbroek 
2079c38dbb97SDavid van Moolenbroek 	put_equals(proc);
2080c38dbb97SDavid van Moolenbroek 	put_result(proc);
2081c38dbb97SDavid van Moolenbroek }
2082c38dbb97SDavid van Moolenbroek 
2083c38dbb97SDavid van Moolenbroek static int
vfs_recvmsg_out(struct trace_proc * proc,const message * m_out)2084c38dbb97SDavid van Moolenbroek vfs_recvmsg_out(struct trace_proc * proc, const message * m_out)
2085c38dbb97SDavid van Moolenbroek {
2086c38dbb97SDavid van Moolenbroek 
2087c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sockmsg.fd);
2088c38dbb97SDavid van Moolenbroek 
2089c38dbb97SDavid van Moolenbroek 	return CT_NOTDONE;
2090c38dbb97SDavid van Moolenbroek }
2091c38dbb97SDavid van Moolenbroek 
2092c38dbb97SDavid van Moolenbroek static void
vfs_recvmsg_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)2093c38dbb97SDavid van Moolenbroek vfs_recvmsg_in(struct trace_proc * proc, const message * m_out,
2094c38dbb97SDavid van Moolenbroek 	const message * m_in, int failed)
2095c38dbb97SDavid van Moolenbroek {
2096c38dbb97SDavid van Moolenbroek 
2097c38dbb97SDavid van Moolenbroek 	/*
2098c38dbb97SDavid van Moolenbroek 	 * We choose to print only the resulting structure in this case.  Doing
2099c38dbb97SDavid van Moolenbroek 	 * so is easier and less messy than printing both the original and the
2100c38dbb97SDavid van Moolenbroek 	 * result for the fields that are updated by the system (msg_namelen
2101c38dbb97SDavid van Moolenbroek 	 * and msg_controllen); also, this approach is stateless.  Admittedly
2102c38dbb97SDavid van Moolenbroek 	 * it is not entirely consistent with many other parts of the trace
2103c38dbb97SDavid van Moolenbroek 	 * output, though.
2104c38dbb97SDavid van Moolenbroek 	 */
2105c38dbb97SDavid van Moolenbroek 	put_struct_msghdr(proc, "msg", PF_ALT | failed,
2106c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockmsg.msgbuf, m_in->m_type);
2107c38dbb97SDavid van Moolenbroek 	put_flags(proc, "flags", msg_flags, COUNT(msg_flags), "0x%x",
2108c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockmsg.flags);
2109c38dbb97SDavid van Moolenbroek 
2110c38dbb97SDavid van Moolenbroek 	put_equals(proc);
2111c38dbb97SDavid van Moolenbroek 	put_result(proc);
2112c38dbb97SDavid van Moolenbroek }
2113c38dbb97SDavid van Moolenbroek 
2114c38dbb97SDavid van Moolenbroek static void
put_sockopt_name(struct trace_proc * proc,const char * name,int level,int optname)2115c38dbb97SDavid van Moolenbroek put_sockopt_name(struct trace_proc * proc, const char * name, int level,
2116c38dbb97SDavid van Moolenbroek 	int optname)
2117c38dbb97SDavid van Moolenbroek {
2118c38dbb97SDavid van Moolenbroek 	const char *text = NULL;
2119c38dbb97SDavid van Moolenbroek 
2120c38dbb97SDavid van Moolenbroek 	/*
2121c38dbb97SDavid van Moolenbroek 	 * The only level for which we can know names is SOL_SOCKET.  See also
2122c38dbb97SDavid van Moolenbroek 	 * put_socket_level().  Of course we could guess, but then we need a
2123c38dbb97SDavid van Moolenbroek 	 * proper guessing system, which should probably also take into account
2124c38dbb97SDavid van Moolenbroek 	 * the [gs]etsockopt option length.  TODO.
2125c38dbb97SDavid van Moolenbroek 	 */
2126c38dbb97SDavid van Moolenbroek 	if (!valuesonly && level == SOL_SOCKET) {
2127c38dbb97SDavid van Moolenbroek 		switch (optname) {
2128c38dbb97SDavid van Moolenbroek 		TEXT(SO_DEBUG);
2129c38dbb97SDavid van Moolenbroek 		TEXT(SO_ACCEPTCONN);
2130c38dbb97SDavid van Moolenbroek 		TEXT(SO_REUSEADDR);
2131c38dbb97SDavid van Moolenbroek 		TEXT(SO_KEEPALIVE);
2132c38dbb97SDavid van Moolenbroek 		TEXT(SO_DONTROUTE);
2133c38dbb97SDavid van Moolenbroek 		TEXT(SO_BROADCAST);
2134c38dbb97SDavid van Moolenbroek 		TEXT(SO_USELOOPBACK);
2135c38dbb97SDavid van Moolenbroek 		TEXT(SO_LINGER);
2136c38dbb97SDavid van Moolenbroek 		TEXT(SO_OOBINLINE);
2137c38dbb97SDavid van Moolenbroek 		TEXT(SO_REUSEPORT);
2138c38dbb97SDavid van Moolenbroek 		TEXT(SO_NOSIGPIPE);
2139c38dbb97SDavid van Moolenbroek 		TEXT(SO_TIMESTAMP);
2140c38dbb97SDavid van Moolenbroek 		TEXT(SO_SNDBUF);
2141c38dbb97SDavid van Moolenbroek 		TEXT(SO_RCVBUF);
2142c38dbb97SDavid van Moolenbroek 		TEXT(SO_SNDLOWAT);
2143c38dbb97SDavid van Moolenbroek 		TEXT(SO_RCVLOWAT);
2144c38dbb97SDavid van Moolenbroek 		TEXT(SO_ERROR);
2145c38dbb97SDavid van Moolenbroek 		TEXT(SO_TYPE);
2146c38dbb97SDavid van Moolenbroek 		TEXT(SO_OVERFLOWED);
2147c38dbb97SDavid van Moolenbroek 		TEXT(SO_NOHEADER);
2148c38dbb97SDavid van Moolenbroek 		TEXT(SO_SNDTIMEO);
2149c38dbb97SDavid van Moolenbroek 		TEXT(SO_RCVTIMEO);
2150c38dbb97SDavid van Moolenbroek 		}
2151c38dbb97SDavid van Moolenbroek 	}
2152c38dbb97SDavid van Moolenbroek 
2153c38dbb97SDavid van Moolenbroek 	if (text != NULL)
2154c38dbb97SDavid van Moolenbroek 		put_field(proc, name, text);
2155c38dbb97SDavid van Moolenbroek 	else
2156c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "0x%x", optname);
2157c38dbb97SDavid van Moolenbroek }
2158c38dbb97SDavid van Moolenbroek 
2159c38dbb97SDavid van Moolenbroek static void
put_sockopt_data(struct trace_proc * proc,const char * name,int flags,int level,int optname,vir_bytes addr,socklen_t len)2160c38dbb97SDavid van Moolenbroek put_sockopt_data(struct trace_proc * proc, const char * name, int flags,
2161c38dbb97SDavid van Moolenbroek 	int level, int optname, vir_bytes addr, socklen_t len)
2162c38dbb97SDavid van Moolenbroek {
2163c38dbb97SDavid van Moolenbroek 	const char *text;
2164c38dbb97SDavid van Moolenbroek 	int i;
2165c38dbb97SDavid van Moolenbroek 	struct linger l;
2166c38dbb97SDavid van Moolenbroek 	struct timeval tv;
2167c38dbb97SDavid van Moolenbroek 	void *ptr;
2168c38dbb97SDavid van Moolenbroek 	size_t size;
2169c38dbb97SDavid van Moolenbroek 
2170c38dbb97SDavid van Moolenbroek 	/* See above regarding ambiguity for levels other than SOL_SOCKET. */
2171c38dbb97SDavid van Moolenbroek 	if ((flags & PF_FAILED) || valuesonly > 1 || len == 0 ||
2172c38dbb97SDavid van Moolenbroek 	    level != SOL_SOCKET) {
2173c38dbb97SDavid van Moolenbroek 		put_ptr(proc, name, addr);
2174c38dbb97SDavid van Moolenbroek 
2175c38dbb97SDavid van Moolenbroek 		return;
2176c38dbb97SDavid van Moolenbroek 	}
2177c38dbb97SDavid van Moolenbroek 
2178c38dbb97SDavid van Moolenbroek 	/* Determine how much data to get, and where to put it. */
2179c38dbb97SDavid van Moolenbroek 	switch (optname) {
2180c38dbb97SDavid van Moolenbroek 	case SO_DEBUG:
2181c38dbb97SDavid van Moolenbroek 	case SO_ACCEPTCONN:
2182c38dbb97SDavid van Moolenbroek 	case SO_REUSEADDR:
2183c38dbb97SDavid van Moolenbroek 	case SO_KEEPALIVE:
2184c38dbb97SDavid van Moolenbroek 	case SO_DONTROUTE:
2185c38dbb97SDavid van Moolenbroek 	case SO_BROADCAST:
2186c38dbb97SDavid van Moolenbroek 	case SO_USELOOPBACK:
2187c38dbb97SDavid van Moolenbroek 	case SO_OOBINLINE:
2188c38dbb97SDavid van Moolenbroek 	case SO_REUSEPORT:
2189c38dbb97SDavid van Moolenbroek 	case SO_NOSIGPIPE:
2190c38dbb97SDavid van Moolenbroek 	case SO_TIMESTAMP:
2191c38dbb97SDavid van Moolenbroek 	case SO_SNDBUF:
2192c38dbb97SDavid van Moolenbroek 	case SO_RCVBUF:
2193c38dbb97SDavid van Moolenbroek 	case SO_SNDLOWAT:
2194c38dbb97SDavid van Moolenbroek 	case SO_RCVLOWAT:
2195c38dbb97SDavid van Moolenbroek 	case SO_ERROR:
2196c38dbb97SDavid van Moolenbroek 	case SO_TYPE:
2197c38dbb97SDavid van Moolenbroek 	case SO_OVERFLOWED:
2198c38dbb97SDavid van Moolenbroek 	case SO_NOHEADER:
2199c38dbb97SDavid van Moolenbroek 		ptr = &i;
2200c38dbb97SDavid van Moolenbroek 		size = sizeof(i);
2201c38dbb97SDavid van Moolenbroek 		break;
2202c38dbb97SDavid van Moolenbroek 	case SO_LINGER:
2203c38dbb97SDavid van Moolenbroek 		ptr = &l;
2204c38dbb97SDavid van Moolenbroek 		size = sizeof(l);
2205c38dbb97SDavid van Moolenbroek 		break;
2206c38dbb97SDavid van Moolenbroek 	case SO_SNDTIMEO:
2207c38dbb97SDavid van Moolenbroek 	case SO_RCVTIMEO:
2208c38dbb97SDavid van Moolenbroek 		ptr = &tv;
2209c38dbb97SDavid van Moolenbroek 		size = sizeof(tv);
2210c38dbb97SDavid van Moolenbroek 		break;
2211c38dbb97SDavid van Moolenbroek 	default:
2212c38dbb97SDavid van Moolenbroek 		put_ptr(proc, name, addr);
2213c38dbb97SDavid van Moolenbroek 		return;
2214c38dbb97SDavid van Moolenbroek 	}
2215c38dbb97SDavid van Moolenbroek 
2216c38dbb97SDavid van Moolenbroek 	/* Get the data.  Do not bother with truncated values. */
2217c38dbb97SDavid van Moolenbroek 	if (len < size || mem_get_data(proc->pid, addr, ptr, size) < 0) {
2218c38dbb97SDavid van Moolenbroek 		put_ptr(proc, name, addr);
2219c38dbb97SDavid van Moolenbroek 
2220c38dbb97SDavid van Moolenbroek 		return;
2221c38dbb97SDavid van Moolenbroek 	}
2222c38dbb97SDavid van Moolenbroek 
2223c38dbb97SDavid van Moolenbroek 	/* Print the data according to the option name. */
2224c38dbb97SDavid van Moolenbroek 	switch (optname) {
2225c38dbb97SDavid van Moolenbroek 	case SO_LINGER:
2226c38dbb97SDavid van Moolenbroek 		/* This isn't going to appear anywhere else; do it inline. */
2227c38dbb97SDavid van Moolenbroek 		put_open(proc, name, 0, "{", ", ");
2228c38dbb97SDavid van Moolenbroek 		put_value(proc, "l_onoff", "%d", l.l_onoff);
2229c38dbb97SDavid van Moolenbroek 		put_value(proc, "l_linger", "%d", l.l_linger);
2230c38dbb97SDavid van Moolenbroek 		put_close(proc, "}");
2231c38dbb97SDavid van Moolenbroek 		break;
2232c38dbb97SDavid van Moolenbroek 	case SO_ERROR:
2233c38dbb97SDavid van Moolenbroek 		put_open(proc, name, 0, "{", ", ");
2234c38dbb97SDavid van Moolenbroek 		if (!valuesonly && (text = get_error_name(i)) != NULL)
2235c38dbb97SDavid van Moolenbroek 			put_field(proc, NULL, text);
2236c38dbb97SDavid van Moolenbroek 		else
2237c38dbb97SDavid van Moolenbroek 			put_value(proc, NULL, "%d", i);
2238c38dbb97SDavid van Moolenbroek 		put_close(proc, "}");
2239c38dbb97SDavid van Moolenbroek 		break;
2240c38dbb97SDavid van Moolenbroek 	case SO_TYPE:
2241c38dbb97SDavid van Moolenbroek 		put_open(proc, name, 0, "{", ", ");
2242c38dbb97SDavid van Moolenbroek 		put_socket_type(proc, NULL, i);
2243c38dbb97SDavid van Moolenbroek 		put_close(proc, "}");
2244c38dbb97SDavid van Moolenbroek 		break;
2245c38dbb97SDavid van Moolenbroek 	case SO_SNDTIMEO:
2246c38dbb97SDavid van Moolenbroek 	case SO_RCVTIMEO:
2247c38dbb97SDavid van Moolenbroek 		put_struct_timeval(proc, name, PF_LOCADDR, (vir_bytes)&tv);
2248c38dbb97SDavid van Moolenbroek 		break;
2249c38dbb97SDavid van Moolenbroek 	default:
2250c38dbb97SDavid van Moolenbroek 		/* All other options are integer values. */
2251c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "{%d}", i);
2252c38dbb97SDavid van Moolenbroek 	}
2253c38dbb97SDavid van Moolenbroek }
2254c38dbb97SDavid van Moolenbroek 
2255c38dbb97SDavid van Moolenbroek static int
vfs_setsockopt_out(struct trace_proc * proc,const message * m_out)2256c38dbb97SDavid van Moolenbroek vfs_setsockopt_out(struct trace_proc * proc, const message * m_out)
2257c38dbb97SDavid van Moolenbroek {
2258c38dbb97SDavid van Moolenbroek 	int level, name;
2259c38dbb97SDavid van Moolenbroek 
2260c38dbb97SDavid van Moolenbroek 	level = m_out->m_lc_vfs_sockopt.level;
2261c38dbb97SDavid van Moolenbroek 	name = m_out->m_lc_vfs_sockopt.name;
2262c38dbb97SDavid van Moolenbroek 
2263c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sockopt.fd);
2264c38dbb97SDavid van Moolenbroek 	put_socket_level(proc, "level", level);
2265c38dbb97SDavid van Moolenbroek 	put_sockopt_name(proc, "name", level, name);
2266c38dbb97SDavid van Moolenbroek 	put_sockopt_data(proc, "buf", 0, level, name,
2267c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockopt.buf, m_out->m_lc_vfs_sockopt.len);
2268c38dbb97SDavid van Moolenbroek 	put_value(proc, "len", "%u", m_out->m_lc_vfs_sockopt.len);
2269c38dbb97SDavid van Moolenbroek 
2270c38dbb97SDavid van Moolenbroek 	return CT_DONE;
2271c38dbb97SDavid van Moolenbroek }
2272c38dbb97SDavid van Moolenbroek 
2273c38dbb97SDavid van Moolenbroek static int
vfs_getsockopt_out(struct trace_proc * proc,const message * m_out)2274c38dbb97SDavid van Moolenbroek vfs_getsockopt_out(struct trace_proc * proc, const message * m_out)
2275c38dbb97SDavid van Moolenbroek {
2276c38dbb97SDavid van Moolenbroek 	int level;
2277c38dbb97SDavid van Moolenbroek 
2278c38dbb97SDavid van Moolenbroek 	level = m_out->m_lc_vfs_sockopt.level;
2279c38dbb97SDavid van Moolenbroek 
2280c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sockopt.fd);
2281c38dbb97SDavid van Moolenbroek 	put_socket_level(proc, "level", level);
2282c38dbb97SDavid van Moolenbroek 	put_sockopt_name(proc, "name", level, m_out->m_lc_vfs_sockopt.name);
2283c38dbb97SDavid van Moolenbroek 
2284c38dbb97SDavid van Moolenbroek 	return CT_NOTDONE;
2285c38dbb97SDavid van Moolenbroek }
2286c38dbb97SDavid van Moolenbroek 
2287c38dbb97SDavid van Moolenbroek static void
vfs_getsockopt_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)2288c38dbb97SDavid van Moolenbroek vfs_getsockopt_in(struct trace_proc * proc, const message * m_out,
2289c38dbb97SDavid van Moolenbroek 	const message * m_in, int failed)
2290c38dbb97SDavid van Moolenbroek {
2291c38dbb97SDavid van Moolenbroek 
2292c38dbb97SDavid van Moolenbroek 	put_sockopt_data(proc, "buf", failed, m_out->m_lc_vfs_sockopt.level,
2293c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockopt.name, m_out->m_lc_vfs_sockopt.buf,
2294c38dbb97SDavid van Moolenbroek 	    m_in->m_vfs_lc_socklen.len);
2295c38dbb97SDavid van Moolenbroek 	/*
2296c38dbb97SDavid van Moolenbroek 	 * For the length, we follow the same scheme as for addr_len pointers
2297c38dbb97SDavid van Moolenbroek 	 * in accept() et al., in that we print the result only.  We need not
2298c38dbb97SDavid van Moolenbroek 	 * take into account that the given buffer is NULL as it must not be.
2299c38dbb97SDavid van Moolenbroek 	 */
2300c38dbb97SDavid van Moolenbroek 	if (!failed)
2301c38dbb97SDavid van Moolenbroek 		put_value(proc, "len", "%u", m_out->m_lc_vfs_sockopt.len);
2302c38dbb97SDavid van Moolenbroek 	else
2303c38dbb97SDavid van Moolenbroek 		put_field(proc, "len", "&..");
2304c38dbb97SDavid van Moolenbroek 
2305c38dbb97SDavid van Moolenbroek 	put_equals(proc);
2306c38dbb97SDavid van Moolenbroek 	put_result(proc);
2307c38dbb97SDavid van Moolenbroek }
2308c38dbb97SDavid van Moolenbroek 
2309c38dbb97SDavid van Moolenbroek /* This function is shared between getsockname and getpeername. */
2310c38dbb97SDavid van Moolenbroek static int
vfs_getsockname_out(struct trace_proc * proc,const message * m_out)2311c38dbb97SDavid van Moolenbroek vfs_getsockname_out(struct trace_proc * proc, const message * m_out)
2312c38dbb97SDavid van Moolenbroek {
2313c38dbb97SDavid van Moolenbroek 
2314c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_sockaddr.fd);
2315c38dbb97SDavid van Moolenbroek 
2316c38dbb97SDavid van Moolenbroek 	return CT_NOTDONE;
2317c38dbb97SDavid van Moolenbroek }
2318c38dbb97SDavid van Moolenbroek 
2319c38dbb97SDavid van Moolenbroek static void
vfs_getsockname_in(struct trace_proc * proc,const message * m_out,const message * m_in,int failed)2320c38dbb97SDavid van Moolenbroek vfs_getsockname_in(struct trace_proc * proc, const message * m_out,
2321c38dbb97SDavid van Moolenbroek 	const message * m_in, int failed)
2322c38dbb97SDavid van Moolenbroek {
2323c38dbb97SDavid van Moolenbroek 
2324c38dbb97SDavid van Moolenbroek 	put_struct_sockaddr(proc, "addr", failed,
2325c38dbb97SDavid van Moolenbroek 	    m_out->m_lc_vfs_sockaddr.addr, m_in->m_vfs_lc_socklen.len);
2326c38dbb97SDavid van Moolenbroek 	if (m_out->m_lc_vfs_sockaddr.addr == 0)
2327c38dbb97SDavid van Moolenbroek 		put_field(proc, "addr_len", "NULL");
2328c38dbb97SDavid van Moolenbroek 	else if (!failed)
2329c38dbb97SDavid van Moolenbroek 		put_value(proc, "addr_len", "{%u}",
2330c38dbb97SDavid van Moolenbroek 		    m_in->m_vfs_lc_socklen.len);
2331c38dbb97SDavid van Moolenbroek 	else
2332c38dbb97SDavid van Moolenbroek 		put_field(proc, "addr_len", "&..");
2333c38dbb97SDavid van Moolenbroek 
2334c38dbb97SDavid van Moolenbroek 	put_equals(proc);
2335c38dbb97SDavid van Moolenbroek 	put_result(proc);
2336c38dbb97SDavid van Moolenbroek }
2337c38dbb97SDavid van Moolenbroek 
2338c38dbb97SDavid van Moolenbroek void
put_shutdown_how(struct trace_proc * proc,const char * name,int how)2339c38dbb97SDavid van Moolenbroek put_shutdown_how(struct trace_proc * proc, const char * name, int how)
2340c38dbb97SDavid van Moolenbroek {
2341c38dbb97SDavid van Moolenbroek 	const char *text = NULL;
2342c38dbb97SDavid van Moolenbroek 
2343c38dbb97SDavid van Moolenbroek 	if (!valuesonly) {
2344c38dbb97SDavid van Moolenbroek 		switch (how) {
2345c38dbb97SDavid van Moolenbroek 		TEXT(SHUT_RD);
2346c38dbb97SDavid van Moolenbroek 		TEXT(SHUT_WR);
2347c38dbb97SDavid van Moolenbroek 		TEXT(SHUT_RDWR);
2348c38dbb97SDavid van Moolenbroek 		}
2349c38dbb97SDavid van Moolenbroek 	}
2350c38dbb97SDavid van Moolenbroek 
2351c38dbb97SDavid van Moolenbroek 	if (text != NULL)
2352c38dbb97SDavid van Moolenbroek 		put_field(proc, name, text);
2353c38dbb97SDavid van Moolenbroek 	else
2354c38dbb97SDavid van Moolenbroek 		put_value(proc, name, "%d", how);
2355c38dbb97SDavid van Moolenbroek }
2356c38dbb97SDavid van Moolenbroek 
2357c38dbb97SDavid van Moolenbroek static int
vfs_shutdown_out(struct trace_proc * proc,const message * m_out)2358c38dbb97SDavid van Moolenbroek vfs_shutdown_out(struct trace_proc * proc, const message * m_out)
2359c38dbb97SDavid van Moolenbroek {
2360c38dbb97SDavid van Moolenbroek 
2361c38dbb97SDavid van Moolenbroek 	put_fd(proc, "fd", m_out->m_lc_vfs_shutdown.fd);
2362c38dbb97SDavid van Moolenbroek 	put_shutdown_how(proc, "how", m_out->m_lc_vfs_shutdown.how);
2363c38dbb97SDavid van Moolenbroek 
2364c38dbb97SDavid van Moolenbroek 	return CT_DONE;
2365c38dbb97SDavid van Moolenbroek }
2366c38dbb97SDavid van Moolenbroek 
2367521fa314SDavid van Moolenbroek #define VFS_CALL(c) [((VFS_ ## c) - VFS_BASE)]
2368521fa314SDavid van Moolenbroek 
2369521fa314SDavid van Moolenbroek static const struct call_handler vfs_map[] = {
2370521fa314SDavid van Moolenbroek 	VFS_CALL(READ) = HANDLER("read", vfs_read_out, vfs_read_in),
2371521fa314SDavid van Moolenbroek 	VFS_CALL(WRITE) = HANDLER("write", vfs_write_out, default_in),
2372521fa314SDavid van Moolenbroek 	VFS_CALL(LSEEK) = HANDLER("lseek", vfs_lseek_out, vfs_lseek_in),
2373521fa314SDavid van Moolenbroek 	VFS_CALL(OPEN) = HANDLER("open", vfs_open_out, vfs_open_in),
2374521fa314SDavid van Moolenbroek 	VFS_CALL(CREAT) = HANDLER("open", vfs_creat_out, vfs_open_in),
2375521fa314SDavid van Moolenbroek 	VFS_CALL(CLOSE) = HANDLER("close", vfs_close_out, default_in),
2376521fa314SDavid van Moolenbroek 	VFS_CALL(LINK) = HANDLER("link", vfs_link_out, default_in),
2377521fa314SDavid van Moolenbroek 	VFS_CALL(UNLINK) = HANDLER("unlink", vfs_path_out, default_in),
2378521fa314SDavid van Moolenbroek 	VFS_CALL(CHDIR) = HANDLER("chdir", vfs_path_out, default_in),
2379521fa314SDavid van Moolenbroek 	VFS_CALL(MKDIR) = HANDLER("mkdir", vfs_path_mode_out, default_in),
2380521fa314SDavid van Moolenbroek 	VFS_CALL(MKNOD) = HANDLER("mknod", vfs_mknod_out, default_in),
2381521fa314SDavid van Moolenbroek 	VFS_CALL(CHMOD) = HANDLER("chmod", vfs_path_mode_out, default_in),
2382521fa314SDavid van Moolenbroek 	VFS_CALL(CHOWN) = HANDLER("chown", vfs_chown_out, default_in),
2383521fa314SDavid van Moolenbroek 	VFS_CALL(MOUNT) = HANDLER("mount", vfs_mount_out, default_in),
2384521fa314SDavid van Moolenbroek 	VFS_CALL(UMOUNT) = HANDLER("umount", vfs_umount_out, vfs_umount_in),
2385521fa314SDavid van Moolenbroek 	VFS_CALL(ACCESS) = HANDLER("access", vfs_access_out, default_in),
2386521fa314SDavid van Moolenbroek 	VFS_CALL(SYNC) = HANDLER("sync", default_out, default_in),
2387521fa314SDavid van Moolenbroek 	VFS_CALL(RENAME) = HANDLER("rename", vfs_link_out, default_in),
2388521fa314SDavid van Moolenbroek 	VFS_CALL(RMDIR) = HANDLER("rmdir", vfs_path_out, default_in),
2389521fa314SDavid van Moolenbroek 	VFS_CALL(SYMLINK) = HANDLER("symlink", vfs_link_out, default_in),
2390521fa314SDavid van Moolenbroek 	VFS_CALL(READLINK) = HANDLER("readlink", vfs_readlink_out,
2391521fa314SDavid van Moolenbroek 	    vfs_readlink_in),
2392521fa314SDavid van Moolenbroek 	VFS_CALL(STAT) = HANDLER("stat", vfs_stat_out, vfs_stat_in),
2393521fa314SDavid van Moolenbroek 	VFS_CALL(FSTAT) = HANDLER("fstat", vfs_fstat_out, vfs_fstat_in),
2394521fa314SDavid van Moolenbroek 	VFS_CALL(LSTAT) = HANDLER("lstat", vfs_stat_out, vfs_stat_in),
2395521fa314SDavid van Moolenbroek 	VFS_CALL(IOCTL) = HANDLER("ioctl", vfs_ioctl_out, vfs_ioctl_in),
2396521fa314SDavid van Moolenbroek 	VFS_CALL(FCNTL) = HANDLER("fcntl", vfs_fcntl_out, vfs_fcntl_in),
2397521fa314SDavid van Moolenbroek 	VFS_CALL(PIPE2) = HANDLER("pipe2", vfs_pipe2_out, vfs_pipe2_in),
2398521fa314SDavid van Moolenbroek 	VFS_CALL(UMASK) = HANDLER("umask", vfs_umask_out, vfs_umask_in),
2399521fa314SDavid van Moolenbroek 	VFS_CALL(CHROOT) = HANDLER("chroot", vfs_path_out, default_in),
2400521fa314SDavid van Moolenbroek 	VFS_CALL(GETDENTS) = HANDLER("getdents", vfs_getdents_out,
2401521fa314SDavid van Moolenbroek 	    vfs_getdents_in),
2402521fa314SDavid van Moolenbroek 	VFS_CALL(SELECT) = HANDLER("select", vfs_select_out, vfs_select_in),
2403521fa314SDavid van Moolenbroek 	VFS_CALL(FCHDIR) = HANDLER("fchdir", vfs_fchdir_out, default_in),
2404521fa314SDavid van Moolenbroek 	VFS_CALL(FSYNC) = HANDLER("fsync", vfs_fsync_out, default_in),
2405521fa314SDavid van Moolenbroek 	VFS_CALL(TRUNCATE) = HANDLER("truncate", vfs_truncate_out, default_in),
2406521fa314SDavid van Moolenbroek 	VFS_CALL(FTRUNCATE) = HANDLER("ftruncate", vfs_ftruncate_out,
2407521fa314SDavid van Moolenbroek 	    default_in),
2408521fa314SDavid van Moolenbroek 	VFS_CALL(FCHMOD) = HANDLER("fchmod", vfs_fchmod_out, default_in),
2409521fa314SDavid van Moolenbroek 	VFS_CALL(FCHOWN) = HANDLER("fchown", vfs_fchown_out, default_in),
2410521fa314SDavid van Moolenbroek 	VFS_CALL(UTIMENS) = HANDLER_NAME(vfs_utimens_name, vfs_utimens_out,
2411521fa314SDavid van Moolenbroek 	    default_in),
2412521fa314SDavid van Moolenbroek 	VFS_CALL(GETVFSSTAT) = HANDLER("getvfsstat", vfs_getvfsstat_out,
2413521fa314SDavid van Moolenbroek 	    vfs_getvfsstat_in),
2414521fa314SDavid van Moolenbroek 	VFS_CALL(STATVFS1) = HANDLER("statvfs1", vfs_statvfs1_out,
2415521fa314SDavid van Moolenbroek 	    vfs_statvfs1_in),
2416521fa314SDavid van Moolenbroek 	VFS_CALL(FSTATVFS1) = HANDLER("fstatvfs1", vfs_fstatvfs1_out,
2417521fa314SDavid van Moolenbroek 	    vfs_statvfs1_in),
2418521fa314SDavid van Moolenbroek 	VFS_CALL(SVRCTL) = HANDLER("vfs_svrctl", vfs_svrctl_out,
2419521fa314SDavid van Moolenbroek 	    vfs_svrctl_in),
2420521fa314SDavid van Moolenbroek 	VFS_CALL(GCOV_FLUSH) = HANDLER("gcov_flush", vfs_gcov_flush_out,
2421521fa314SDavid van Moolenbroek 	    default_in),
2422c38dbb97SDavid van Moolenbroek 	VFS_CALL(SOCKET) = HANDLER("socket", vfs_socket_out, default_in),
2423c38dbb97SDavid van Moolenbroek 	VFS_CALL(SOCKETPAIR) = HANDLER("socketpair", vfs_socketpair_out,
2424c38dbb97SDavid van Moolenbroek 	    vfs_socketpair_in),
2425c38dbb97SDavid van Moolenbroek 	VFS_CALL(BIND) = HANDLER("bind", vfs_bind_out, default_in),
2426c38dbb97SDavid van Moolenbroek 	VFS_CALL(CONNECT) = HANDLER("connect", vfs_bind_out, default_in),
2427c38dbb97SDavid van Moolenbroek 	VFS_CALL(LISTEN) = HANDLER("listen", vfs_listen_out, default_in),
2428c38dbb97SDavid van Moolenbroek 	VFS_CALL(ACCEPT) = HANDLER("accept", vfs_accept_out, vfs_accept_in),
2429c38dbb97SDavid van Moolenbroek 	VFS_CALL(SENDTO) = HANDLER("sendto", vfs_sendto_out, default_in),
2430c38dbb97SDavid van Moolenbroek 	VFS_CALL(SENDMSG) = HANDLER("sendmsg", vfs_sendmsg_out, default_in),
2431c38dbb97SDavid van Moolenbroek 	VFS_CALL(RECVFROM) = HANDLER("recvfrom", vfs_recvfrom_out,
2432c38dbb97SDavid van Moolenbroek 	    vfs_recvfrom_in),
2433c38dbb97SDavid van Moolenbroek 	VFS_CALL(RECVMSG) = HANDLER("recvmsg", vfs_recvmsg_out,
2434c38dbb97SDavid van Moolenbroek 	    vfs_recvmsg_in),
2435c38dbb97SDavid van Moolenbroek 	VFS_CALL(SETSOCKOPT) = HANDLER("setsockopt", vfs_setsockopt_out,
2436c38dbb97SDavid van Moolenbroek 	    default_in),
2437c38dbb97SDavid van Moolenbroek 	VFS_CALL(GETSOCKOPT) = HANDLER("getsockopt", vfs_getsockopt_out,
2438c38dbb97SDavid van Moolenbroek 	    vfs_getsockopt_in),
2439c38dbb97SDavid van Moolenbroek 	VFS_CALL(GETSOCKNAME) = HANDLER("getsockname", vfs_getsockname_out,
2440c38dbb97SDavid van Moolenbroek 	    vfs_getsockname_in),
2441c38dbb97SDavid van Moolenbroek 	VFS_CALL(GETPEERNAME) = HANDLER("getpeername", vfs_getsockname_out,
2442c38dbb97SDavid van Moolenbroek 	    vfs_getsockname_in),
2443c38dbb97SDavid van Moolenbroek 	VFS_CALL(SHUTDOWN) = HANDLER("shutdown", vfs_shutdown_out, default_in),
2444521fa314SDavid van Moolenbroek };
2445521fa314SDavid van Moolenbroek 
2446521fa314SDavid van Moolenbroek const struct calls vfs_calls = {
2447521fa314SDavid van Moolenbroek 	.endpt = VFS_PROC_NR,
2448521fa314SDavid van Moolenbroek 	.base = VFS_BASE,
2449521fa314SDavid van Moolenbroek 	.map = vfs_map,
2450521fa314SDavid van Moolenbroek 	.count = COUNT(vfs_map)
2451521fa314SDavid van Moolenbroek };
2452