#include #include #include #include #include #include <9p.h> #include typedef struct Ramfile Ramfile; struct Ramfile { char* data; int ndata; }; static char Ebad[] = "something bad happened"; static char Enomem[] = "no memory"; static char* addr; static char* vname; static void fsattach(Req* r) { if (r->srv->auth != nil && authattach(r) < 0) return; respond(r, nil); } static void fsopen(Req* r) { Ramfile*rf; File* file; if (r->fid->qid.type&QTAUTH) sysfatal("fsopen for an AUTH file. fixme: add respond/return\n"); file = r->fid->file; if (r->ifcall.mode&OTRUNC){ rf = file->aux; if(rf){ rf->ndata = 0; file->length = 0; } } respond(r, nil); } static void fscreate(Req* r) { File *file; char* name; char* uid; int mode; Ramfile *rf; File* f; file = r->fid->file; name = r->ifcall.name; uid = r->fid->uid; mode = r->fid->file->mode & 0x777 & r->ifcall.perm; mode |= (r->ifcall.perm & ~0x777); if(f = createfile(file, name, uid, mode, 0)){ rf = emalloc9p(sizeof *rf); f->aux = rf; closefile(r->fid->file); r->fid->file = f; r->ofcall.qid = f->qid; respond(r, nil); } else responderror(r); } static void fsread(Req* r) { File* file; long count; vlong offset; Ramfile*rf; if (r->fid->qid.type&QTAUTH){ authread(r); return; } file = r->fid->file; rf = file->aux; offset = r->ifcall.offset; count = r->ifcall.count; if (offset >= rf->ndata){ count = 0; } else { if(offset+count >= rf->ndata) count = rf->ndata - offset; memmove(r->ofcall.data, rf->data+offset, count); } r->ofcall.count = count; respond(r, nil); } static void fswrite(Req* r) { File* file; long count; vlong offset; Ramfile*rf; void* v; if (r->fid->qid.type&QTAUTH){ authwrite(r); return; } file = r->fid->file; rf = file->aux; offset = r->ifcall.offset; count = r->ifcall.count; if(offset+count >= rf->ndata){ v = realloc(rf->data, offset+count); if(v == nil){ respond(r, Enomem); return; } else { rf->data = v; rf->ndata = offset+count; file->length = rf->ndata; } } if (r->ofcall.count = count) memmove(rf->data+offset, r->ifcall.data, count); respond(r, nil); } static void fswstat(Req* r) { if (r->d.name && r->d.name[0] && strcmp(r->fid->file->name, r->d.name)){ free(r->fid->file->name); r->fid->file->name = estrdup9p(r->d.name); } if (r->d.uid && r->d.uid[0]){ free(r->fid->file->uid); r->fid->file->uid = estrdup9p(r->d.uid); } if (r->d.gid && r->d.gid[0]){ free(r->fid->file->gid); r->fid->file->gid = estrdup9p(r->d.gid); } if (~(ulong)r->d.mode) r->fid->file->mode = r->d.mode; respond(r, nil); } static void fsclunk(Fid* fid) { if (fid->qid.type&QTAUTH) authdestroy(fid); } static int islocal(char* addr) { static char* l = nil; if (addr == nil) return 1; if (!strncmp(addr, "::", 2) || !strncmp(addr, "127.0.0.1", 8)) return 1; if (l == nil) l = getenv("sysaddr"); if (l && !strncmp(addr, l, strlen(l))) return 1; return 0; } static void bauth9p(Req* r) { if (islocal(r->srv->addr)) { r->srv->auth = nil; // no auth here any more respond(r, "auth no required for local peers"); } else auth9p(r); } static Srv sfs= { .auth = bauth9p, .attach = fsattach, .open = fsopen, .create = fscreate, .read = fsread, .wstat = fswstat, .write = fswrite, .destroyfid = fsclunk, }; static void freefile(File *f) { Ramfile *rf; rf = f->aux; if(rf){ f->aux = nil; free(rf->data); free(rf); } } static void announceproc(void*) { int afd = -1; char* cnstr; cnstr = strchr(vname, ' '); if (cnstr) *cnstr++ = 0; for(;;){ afd = announcevol(afd, addr, vname, cnstr); sleep(10 * 1000); } } void usage(void) { fprint(2, "usage: %s [-abcAD] [-s srv] [-m mnt] [-n addr] [-V vol]\n", argv0); exits("usage"); } void threadmain(int argc, char **argv) { char* mnt; char* srv; int mflag; srv = nil; mnt = nil; mflag = MREPL|MCREATE; ARGBEGIN{ case 'a': mflag = MAFTER|MCREATE; break; case 'b': mflag = MBEFORE|MCREATE; break; case 'c': mflag = MREPL|MCREATE; break; case 'A': sfs.auth = nil; break; case 'd': chatty9p++; break; case 's': srv = EARGF(usage()); break; case 'm': mnt = EARGF(usage()); break; case 'n': addr = EARGF(usage()); break; case 'V': vname = EARGF(usage()); break; default: usage(); }ARGEND; if(argc!= 0) usage(); if (getenv("local")) sfs.auth = nil; if (srv == nil && mnt == nil && addr == nil){ sfs.auth = nil; mnt = "/tmp"; } if (!chatty9p) rfork(RFNOTEG); sfs.tree = alloctree(nil, nil, DMDIR|0755, freefile); if (addr != nil){ threadlistensrv(&sfs, addr); } if (srv != nil || mnt != nil) threadpostmountsrv(&sfs, srv, mnt, mflag); if (addr != nil && vname != nil) proccreate(announceproc, 0, 8*1024); threadexits(nil); }