libfuse
stracedecode.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "fuse_kernel.h"
4 
5 static 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 
49 static 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 
58 static 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 
120 int 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 }