ref: 7d85dc87bcb5ab2cc6c032bf0ae4eef3bdf14c21
dir: /test/freplay.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <thread.h> #include <9p.h> char* mountpt = "/n/replay"; char* logfile; char* replayfile; char* membuf; vlong membufsz; vlong replaycount = -1; int logfd; void log1(int fd, void *buf, vlong off, vlong sz) { char *p, hdr[12]; p = hdr; PBIT64(p, off); p += 8; PBIT32(p, sz); if(write(fd, hdr, sizeof(hdr)) == -1) sysfatal("write header: %r"); if(write(fd, buf, sz) == -1) sysfatal("write data: %r\n"); } int replay1(int fd) { uchar *p, hdr[12]; vlong o; int n, r; r = readn(fd, hdr, 12); if(r == 0) return 0; if(r != 12) sysfatal("failed to read operation header: %r"); p = hdr; o = GBIT64(p); p += 8; n = GBIT32(p); if(o + n > membufsz) sysfatal("operation exceeds buffer size"); if(readn(fd, membuf + o, n) != n) sysfatal("read op: %r"); return 1; } void fsread(Req *r) { readbuf(r, membuf, membufsz); respond(r, nil); } void fswrite(Req *r) { if(r->ifcall.offset + r->ifcall.count >= membufsz) respond(r, "operation exceeds file size"); log1(logfd, r->ifcall.data, r->ifcall.offset, r->ifcall.count); memcpy(membuf + r->ifcall.offset, r->ifcall.data, r->ifcall.count); r->ofcall.count = r->ifcall.count; respond(r, nil); } void usage(void) { fprint(2, "usage: %s -l log [-r replay] [-c count] file\n", argv0); exits("usage"); } static Srv fs = { .read = fsread, .write = fswrite, }; void main(int argc, char *argv[]) { int fd, replayfd; vlong n, off; char *uid; File *f; Dir *d; int i; ARGBEGIN{ case 'd': chatty9p++; break; case 'l': logfile = EARGF(usage()); break; case 'r': replayfile = EARGF(usage()); break; case 'c': replaycount = atoi(EARGF(usage())); break; case 'm': mountpt = EARGF(usage()); break; default: usage(); }ARGEND; if(argc != 1 || logfile == nil) usage(); if((fd = open(argv[0], OREAD)) == -1) sysfatal("open %s: %r", argv[0]); if((d = dirfstat(fd)) == nil) sysfatal("failed to stat file: %r"); if((membuf = mallocz(d->length, 1)) == nil) sysfatal("failed to allocate buffer: %r"); for(off = 0; off < d->length; off += n) if((n = read(fd, membuf+off, d->length - off)) <= 0) sysfatal("read %s: short read", argv[0]); membufsz = d->length; free(d); if(replayfile != nil){ if((replayfd = open(replayfile, OREAD)) == -1) sysfatal("failed to open replay file: %r"); for(i = 0; i < replaycount || replaycount == -1; i++) if(replay1(replayfd) == 0) break; close(replayfd); } if((logfd = create(logfile, OWRITE, 0666)) == -1) sysfatal("failed to open log file: %r"); uid = getuser(); fs.tree = alloctree(uid, uid, DMDIR|0555, nil); f = createfile(fs.tree->root, "data", uid, 0666, nil); f->length = membufsz; postmountsrv(&fs, nil, mountpt, 0); exits(nil); }