xref: /third_party/libfuse/test/stracedecode.c (revision 6881f68f)
1#include <stdio.h>
2#include <string.h>
3#include "fuse_kernel.h"
4
5static struct {
6	const char *name;
7} fuse_ll_ops[] = {
8	[FUSE_LOOKUP]	   = { "LOOKUP"	     },
9	[FUSE_FORGET]	   = { "FORGET"	     },
10	[FUSE_GETATTR]	   = { "GETATTR"     },
11	[FUSE_SETATTR]	   = { "SETATTR"     },
12	[FUSE_READLINK]	   = { "READLINK"    },
13	[FUSE_SYMLINK]	   = { "SYMLINK"     },
14	[FUSE_MKNOD]	   = { "MKNOD"	     },
15	[FUSE_MKDIR]	   = { "MKDIR"	     },
16	[FUSE_UNLINK]	   = { "UNLINK"	     },
17	[FUSE_RMDIR]	   = { "RMDIR"	     },
18	[FUSE_RENAME]	   = { "RENAME"	     },
19	[FUSE_LINK]	   = { "LINK"	     },
20	[FUSE_OPEN]	   = { "OPEN"	     },
21	[FUSE_READ]	   = { "READ"	     },
22	[FUSE_WRITE]	   = { "WRITE"	     },
23	[FUSE_STATFS]	   = { "STATFS"	     },
24	[FUSE_RELEASE]	   = { "RELEASE"     },
25	[FUSE_FSYNC]	   = { "FSYNC"	     },
26	[FUSE_SETXATTR]	   = { "SETXATTR"    },
27	[FUSE_GETXATTR]	   = { "GETXATTR"    },
28	[FUSE_LISTXATTR]   = { "LISTXATTR"   },
29	[FUSE_REMOVEXATTR] = { "REMOVEXATTR" },
30	[FUSE_FLUSH]	   = { "FLUSH"	     },
31	[FUSE_INIT]	   = { "INIT"	     },
32	[FUSE_OPENDIR]	   = { "OPENDIR"     },
33	[FUSE_READDIR]	   = { "READDIR"     },
34	[FUSE_RELEASEDIR]  = { "RELEASEDIR"  },
35	[FUSE_FSYNCDIR]	   = { "FSYNCDIR"    },
36	[FUSE_GETLK]	   = { "GETLK"	     },
37	[FUSE_SETLK]	   = { "SETLK"	     },
38	[FUSE_SETLKW]	   = { "SETLKW"	     },
39	[FUSE_ACCESS]	   = { "ACCESS"	     },
40	[FUSE_CREATE]	   = { "CREATE"	     },
41	[FUSE_INTERRUPT]   = { "INTERRUPT"   },
42	[FUSE_BMAP]	   = { "BMAP"	     },
43	[FUSE_DESTROY]	   = { "DESTROY"     },
44	[FUSE_READDIRPLUS] = { "READDIRPLUS" },
45};
46
47#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
48
49static const char *opname(enum fuse_opcode opcode)
50{
51	if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
52		return "???";
53	else
54		return fuse_ll_ops[opcode].name;
55}
56
57
58static void process_buf(int dir, char *buf, int len)
59{
60	static unsigned long long prevuniq = -1;
61	static int prevopcode;
62
63	if (!dir) {
64		struct fuse_in_header *in = (struct fuse_in_header *) buf;
65		buf += sizeof(struct fuse_in_header);
66
67		printf("unique: %llu, opcode: %s (%i), nodeid: %lu, len: %i, insize: %i\n",
68		       (unsigned long long) in->unique,
69		       opname((enum fuse_opcode) in->opcode), in->opcode,
70		       (unsigned long) in->nodeid, in->len, len);
71
72		switch (in->opcode) {
73		case FUSE_READ: {
74			struct fuse_read_in *arg = (struct fuse_read_in *) buf;
75			printf("-READ fh:%llu off:%llu siz:%u rfl:%u own:%llu fl:%u\n",
76			       arg->fh, arg->offset, arg->size, arg->read_flags,
77			       arg->lock_owner, arg->flags);
78			break;
79		}
80		case FUSE_WRITE: {
81			struct fuse_write_in *arg = (struct fuse_write_in *) buf;
82			printf("-WRITE fh:%llu off:%llu siz:%u wfl:%u own:%llu fl:%u\n",
83			       arg->fh, arg->offset, arg->size, arg->write_flags,
84			       arg->lock_owner, arg->flags);
85			break;
86		}
87		}
88		prevuniq = in->unique;
89		prevopcode = in->opcode;
90	} else {
91		struct fuse_out_header *out = (struct fuse_out_header *) buf;
92		buf += sizeof(struct fuse_out_header);
93
94		printf("   unique: %llu, error: %i (%s), len: %i, outsize: %i\n",
95		       (unsigned long long) out->unique, out->error,
96		       strerror(-out->error), out->len, len);
97
98		if (out->unique == prevuniq) {
99			switch (prevopcode) {
100			case FUSE_GETATTR: {
101				struct fuse_attr_out *arg = (struct fuse_attr_out *) buf;
102				printf("+ATTR v:%llu.%09u i:%llu s:%llu b:%llu\n",
103				       arg->attr_valid, arg->attr_valid_nsec,
104				       arg->attr.ino, arg->attr.size, arg->attr.blocks);
105				break;
106			}
107			case FUSE_LOOKUP: {
108				struct fuse_entry_out *arg = (struct fuse_entry_out *) buf;
109				printf("+ENTRY nodeid:%llu v:%llu.%09u i:%llu s:%llu b:%llu\n",
110				       arg->nodeid, arg->attr_valid, arg->attr_valid_nsec,
111				       arg->attr.ino, arg->attr.size, arg->attr.blocks);
112				break;
113			}
114			}
115		}
116	}
117
118}
119
120int main(void)
121{
122	FILE *in = stdin;
123	while (1) {
124		int dir;
125		int res;
126		char buf[1048576];
127		unsigned len = 0;
128
129		memset(buf, 0, sizeof(buf));
130		while (1) {
131			char str[32];
132
133			res = fscanf(in, "%30s", str);
134			if (res != 1 && feof(in))
135				return 0;
136
137			if (res == 0)
138				continue;
139
140			if (strncmp(str, "read(", 5) == 0) {
141				dir = 0;
142				break;
143			} else if (strncmp(str, "writev(", 7) == 0) {
144				dir = 1;
145				break;
146			}
147		}
148
149		while (1) {
150			int c = getc(in);
151			if (c == '"') {
152				while (1) {
153					int val;
154
155					c = getc(in);
156					if (c == EOF) {
157						fprintf(stderr, "eof in string\n");
158						break;
159					}
160					if (c == '\n') {
161						fprintf(stderr, "eol in string\n");
162						break;
163					}
164					if (c == '"')
165						break;
166					if (c != '\\') {
167						val = c;
168					} else {
169						c = getc(in);
170						switch (c) {
171						case 'n': val = '\n'; break;
172						case 'r': val = '\r'; break;
173						case 't': val = '\t'; break;
174						case '"': val = '"'; break;
175						case '\\': val = '\\'; break;
176						case 'x':
177							res = scanf("%x", &val);
178							if (res != 1) {
179								fprintf(stderr, "parse error\n");
180								continue;
181							}
182							break;
183						default:
184							fprintf(stderr, "unknown sequence: '\\%c'\n", c);
185							continue;
186						}
187					}
188					buf[len++] = val;
189				}
190			}
191			if (c == '\n')
192				break;
193		}
194		process_buf(dir, buf, len);
195		memset(buf, 0, len);
196		len = 0;
197	}
198}
199