stracedecode.c
#include <stdio.h>
#include <string.h>
#include "fuse_kernel.h"
static struct {
const char *name;
} fuse_ll_ops[] = {
[FUSE_LOOKUP] = { "LOOKUP" },
[FUSE_FORGET] = { "FORGET" },
[FUSE_GETATTR] = { "GETATTR" },
[FUSE_SETATTR] = { "SETATTR" },
[FUSE_READLINK] = { "READLINK" },
[FUSE_SYMLINK] = { "SYMLINK" },
[FUSE_MKNOD] = { "MKNOD" },
[FUSE_MKDIR] = { "MKDIR" },
[FUSE_UNLINK] = { "UNLINK" },
[FUSE_RMDIR] = { "RMDIR" },
[FUSE_RENAME] = { "RENAME" },
[FUSE_LINK] = { "LINK" },
[FUSE_OPEN] = { "OPEN" },
[FUSE_READ] = { "READ" },
[FUSE_WRITE] = { "WRITE" },
[FUSE_STATFS] = { "STATFS" },
[FUSE_RELEASE] = { "RELEASE" },
[FUSE_FSYNC] = { "FSYNC" },
[FUSE_SETXATTR] = { "SETXATTR" },
[FUSE_GETXATTR] = { "GETXATTR" },
[FUSE_LISTXATTR] = { "LISTXATTR" },
[FUSE_REMOVEXATTR] = { "REMOVEXATTR" },
[FUSE_FLUSH] = { "FLUSH" },
[FUSE_INIT] = { "INIT" },
[FUSE_OPENDIR] = { "OPENDIR" },
[FUSE_READDIR] = { "READDIR" },
[FUSE_RELEASEDIR] = { "RELEASEDIR" },
[FUSE_FSYNCDIR] = { "FSYNCDIR" },
[FUSE_GETLK] = { "GETLK" },
[FUSE_SETLK] = { "SETLK" },
[FUSE_SETLKW] = { "SETLKW" },
[FUSE_ACCESS] = { "ACCESS" },
[FUSE_CREATE] = { "CREATE" },
[FUSE_INTERRUPT] = { "INTERRUPT" },
[FUSE_BMAP] = { "BMAP" },
[FUSE_DESTROY] = { "DESTROY" },
[FUSE_READDIRPLUS] = { "READDIRPLUS" },
};
#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
static const char *opname(enum fuse_opcode opcode)
{
if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
return "???";
else
return fuse_ll_ops[opcode].name;
}
static void process_buf(int dir, char *buf, int len)
{
static unsigned long long prevuniq = -1;
static int prevopcode;
if (!dir) {
struct fuse_in_header *in = (struct fuse_in_header *) buf;
buf += sizeof(struct fuse_in_header);
printf("unique: %llu, opcode: %s (%i), nodeid: %lu, len: %i, insize: %i\n",
(unsigned long long) in->unique,
opname((enum fuse_opcode) in->opcode), in->opcode,
(unsigned long) in->nodeid, in->len, len);
switch (in->opcode) {
case FUSE_READ: {
struct fuse_read_in *arg = (struct fuse_read_in *) buf;
printf("-READ fh:%llu off:%llu siz:%u rfl:%u own:%llu fl:%u\n",
arg->fh, arg->offset, arg->size, arg->read_flags,
arg->lock_owner, arg->flags);
break;
}
case FUSE_WRITE: {
struct fuse_write_in *arg = (struct fuse_write_in *) buf;
printf("-WRITE fh:%llu off:%llu siz:%u wfl:%u own:%llu fl:%u\n",
arg->fh, arg->offset, arg->size, arg->write_flags,
arg->lock_owner, arg->flags);
break;
}
}
prevuniq = in->unique;
prevopcode = in->opcode;
} else {
struct fuse_out_header *out = (struct fuse_out_header *) buf;
buf += sizeof(struct fuse_out_header);
printf(" unique: %llu, error: %i (%s), len: %i, outsize: %i\n",
(unsigned long long) out->unique, out->error,
strerror(-out->error), out->len, len);
if (out->unique == prevuniq) {
switch (prevopcode) {
case FUSE_GETATTR: {
struct fuse_attr_out *arg = (struct fuse_attr_out *) buf;
printf("+ATTR v:%llu.%09u i:%llu s:%llu b:%llu\n",
arg->attr_valid, arg->attr_valid_nsec,
arg->attr.ino, arg->attr.size, arg->attr.blocks);
break;
}
case FUSE_LOOKUP: {
struct fuse_entry_out *arg = (struct fuse_entry_out *) buf;
printf("+ENTRY nodeid:%llu v:%llu.%09u i:%llu s:%llu b:%llu\n",
arg->nodeid, arg->attr_valid, arg->attr_valid_nsec,
arg->attr.ino, arg->attr.size, arg->attr.blocks);
break;
}
}
}
}
}
int main(void)
{
FILE *in = stdin;
while (1) {
int dir;
int res;
char buf[1048576];
unsigned len = 0;
memset(buf, 0, sizeof(buf));
while (1) {
char str[32];
res = fscanf(in, "%30s", str);
if (res != 1 && feof(in))
return 0;
if (res == 0)
continue;
if (strncmp(str, "read(", 5) == 0) {
dir = 0;
break;
} else if (strncmp(str, "writev(", 7) == 0) {
dir = 1;
break;
}
}
while (1) {
int c = getc(in);
if (c == '"') {
while (1) {
int val;
c = getc(in);
if (c == EOF) {
fprintf(stderr, "eof in string\n");
break;
}
if (c == '\n') {
fprintf(stderr, "eol in string\n");
break;
}
if (c == '"')
break;
if (c != '\\') {
val = c;
} else {
c = getc(in);
switch (c) {
case 'n': val = '\n'; break;
case 'r': val = '\r'; break;
case 't': val = '\t'; break;
case '"': val = '"'; break;
case '\\': val = '\\'; break;
case 'x':
res = scanf("%x", &val);
if (res != 1) {
fprintf(stderr, "parse error\n");
continue;
}
break;
default:
fprintf(stderr, "unknown sequence: '\\%c'\n", c);
continue;
}
}
buf[len++] = val;
}
}
if (c == '\n')
break;
}
process_buf(dir, buf, len);
memset(buf, 0, len);
len = 0;
}
}