libfuse
stracedecode.c
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_TMPFILE] = { "TMPFILE" },
42 [FUSE_INTERRUPT] = { "INTERRUPT" },
43 [FUSE_BMAP] = { "BMAP" },
44 [FUSE_DESTROY] = { "DESTROY" },
45 [FUSE_READDIRPLUS] = { "READDIRPLUS" },
46};
47
48#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
49
50static const char *opname(enum fuse_opcode opcode)
51{
52 if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
53 return "???";
54 else
55 return fuse_ll_ops[opcode].name;
56}
57
58
59static void process_buf(int dir, char *buf, int len)
60{
61 static unsigned long long prevuniq = -1;
62 static int prevopcode;
63
64 if (!dir) {
65 struct fuse_in_header *in = (struct fuse_in_header *) buf;
66 buf += sizeof(struct fuse_in_header);
67
68 printf("unique: %llu, opcode: %s (%i), nodeid: %lu, len: %i, insize: %i\n",
69 (unsigned long long) in->unique,
70 opname((enum fuse_opcode) in->opcode), in->opcode,
71 (unsigned long) in->nodeid, in->len, len);
72
73 switch (in->opcode) {
74 case FUSE_READ: {
75 struct fuse_read_in *arg = (struct fuse_read_in *) buf;
76 printf("-READ fh:%llu off:%llu siz:%u rfl:%u own:%llu fl:%u\n",
77 arg->fh, arg->offset, arg->size, arg->read_flags,
78 arg->lock_owner, arg->flags);
79 break;
80 }
81 case FUSE_WRITE: {
82 struct fuse_write_in *arg = (struct fuse_write_in *) buf;
83 printf("-WRITE fh:%llu off:%llu siz:%u wfl:%u own:%llu fl:%u\n",
84 arg->fh, arg->offset, arg->size, arg->write_flags,
85 arg->lock_owner, arg->flags);
86 break;
87 }
88 }
89 prevuniq = in->unique;
90 prevopcode = in->opcode;
91 } else {
92 struct fuse_out_header *out = (struct fuse_out_header *) buf;
93 buf += sizeof(struct fuse_out_header);
94
95 printf(" unique: %llu, error: %i (%s), len: %i, outsize: %i\n",
96 (unsigned long long) out->unique, out->error,
97 strerror(-out->error), out->len, len);
98
99 if (out->unique == prevuniq) {
100 switch (prevopcode) {
101 case FUSE_GETATTR: {
102 struct fuse_attr_out *arg = (struct fuse_attr_out *) buf;
103 printf("+ATTR v:%llu.%09u i:%llu s:%llu b:%llu\n",
104 arg->attr_valid, arg->attr_valid_nsec,
105 arg->attr.ino, arg->attr.size, arg->attr.blocks);
106 break;
107 }
108 case FUSE_LOOKUP: {
109 struct fuse_entry_out *arg = (struct fuse_entry_out *) buf;
110 printf("+ENTRY nodeid:%llu v:%llu.%09u i:%llu s:%llu b:%llu\n",
111 arg->nodeid, arg->attr_valid, arg->attr_valid_nsec,
112 arg->attr.ino, arg->attr.size, arg->attr.blocks);
113 break;
114 }
115 }
116 }
117 }
118
119}
120
121int main(void)
122{
123 FILE *in = stdin;
124 while (1) {
125 int dir;
126 int res;
127 char buf[1048576];
128 unsigned len = 0;
129
130 memset(buf, 0, sizeof(buf));
131 while (1) {
132 char str[32];
133
134 res = fscanf(in, "%30s", str);
135 if (res != 1 && feof(in))
136 return 0;
137
138 if (res == 0)
139 continue;
140
141 if (strncmp(str, "read(", 5) == 0) {
142 dir = 0;
143 break;
144 } else if (strncmp(str, "writev(", 7) == 0) {
145 dir = 1;
146 break;
147 }
148 }
149
150 while (1) {
151 int c = getc(in);
152 if (c == '"') {
153 while (1) {
154 int val;
155
156 c = getc(in);
157 if (c == EOF) {
158 fprintf(stderr, "eof in string\n");
159 break;
160 }
161 if (c == '\n') {
162 fprintf(stderr, "eol in string\n");
163 break;
164 }
165 if (c == '"')
166 break;
167 if (c != '\\') {
168 val = c;
169 } else {
170 c = getc(in);
171 switch (c) {
172 case 'n': val = '\n'; break;
173 case 'r': val = '\r'; break;
174 case 't': val = '\t'; break;
175 case '"': val = '"'; break;
176 case '\\': val = '\\'; break;
177 case 'x':
178 res = scanf("%x", &val);
179 if (res != 1) {
180 fprintf(stderr, "parse error\n");
181 continue;
182 }
183 break;
184 default:
185 fprintf(stderr, "unknown sequence: '\\%c'\n", c);
186 continue;
187 }
188 }
189 buf[len++] = val;
190 }
191 }
192 if (c == '\n')
193 break;
194 }
195 process_buf(dir, buf, len);
196 memset(buf, 0, len);
197 len = 0;
198 }
199}