<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv=Content-Type content="text/html; charset=utf8"> <title>/usr/web/sources/contrib/maht/actionfs.c - Plan 9 from Bell Labs</title> <!-- THIS FILE IS AUTOMATICALLY GENERATED. --> <!-- EDIT sources.tr INSTEAD. --> </meta> </head> <body> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;"> <span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>’s /usr/web/sources/contrib/maht/actionfs.c</span></p> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <center><font size=-1> Copyright © 2009 Alcatel-Lucent.<br /> Distributed under the <a href="/plan9/license.html">Lucent Public License version 1.02</a>. <br /> <a href="/plan9/download.html">Download the Plan 9 distribution.</a> </font> </center> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <table width="100%" cellspacing=0 border=0><tr><td align="center"> <table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left"> <pre> <!-- END HEADER --> // Put // 8c -w actionfs.c && 8l actionfs.8 && mv 8.out /usr/maht/bin/386/actionfs #include <u.h> #include <libc.h> #include <fcall.h> #include <thread.h> #include <9p.h> #include <regexp.h> #include <stdio.h> typedef struct Path Path; struct Path { Qid qid; char *name; Path *next; }; Reprog *freg; Path *root = nil; int nmatches; int client = 0; static void fsattach(Req *r) { r->ofcall.qid = (Qid){0, ++client, QTDIR}; r->fid->qid = r->ofcall.qid; respond(r, nil); } static void print_qid(Qid *q) { print("p %x v %d f %x\n", q->path, q->vers, q->type); } static void print_matches(Resub *matches) { if(!matches) { print("No match\n"); return; } char *bit; int i, k; for(i = 0; i < nmatches; i++) { k = (matches[i].ep - matches[i].sp) + 1; bit = (char*)malloc(k); strecpy(bit, bit + k, matches[i].sp); free(bit); } print("\n"); } static void print_path(Path *p) { print("Name: %s\n", p->name); print_qid(&p->qid); print("Next: %x\n", p->next); } static Resub* re(char *txt) { Resub* matches = (Resub*)calloc(nmatches, sizeof(Resub)); if(regexec(freg, txt, matches, nmatches)) return matches; free(matches); return nil; } static Path* find_path(Qid *qid) { Path *p; for(p = root; p; p = p->next) if(qid->path == p->qid.path) break; return p; } static Path* find_prev_path(Qid *qid) { Path *p; for(p = root; p; p = p->next) { if(p->next && (qid->path == p->next->qid.path)) break; } return p; } static Qid* find_qid(char *name) { Path *p; Resub *m; for(p = root; p; p = p->next) if(strcmp(name, p->name) == 0) return &p->qid; if(!(m = re(name))) return nil; free(m); p = (Path*)mallocz(sizeof(Path), 1); p->qid.path = root ? root->qid.path +1 : 1; p->qid.vers = 0; p->next = root; p->name = strdup(name); root = p; return &root->qid; } static char* fswalk1(Fid *fid, char *name, Qid *qid) { Qid *q; if(!(q = find_qid(name))) return "Not Found"; q->vers++; memcpy(qid, q, sizeof(Qid)); memcpy(&fid->qid, q, sizeof(Qid)); return nil; } static void fsstat(Req *r) { Path *p; Dir *d = &r->d; memset(d, 0, sizeof *d); d->uid = strdup("inband"); d->gid = strdup("inband"); p = find_path(&r->fid->qid); d->name = strdup(p->name); d->mode = 0444; memcpy(&d->qid, &(r->fid->qid), sizeof(Qid)); d->length = 0; respond(r, nil); } char ** build_argv(int fd, char *name) { char **argv = malloc(sizeof(char*) * (nmatches + 3)); if(fd > 0) argv[0] = smprint("action-read"); else argv[0] = smprint("action-write"); argv[1] = smprint("%d", abs(fd)); Resub *matches = re(name); int i, j, k; for(i = 0, j = 2; i < nmatches; i++, j++) { k = (matches[i].ep - matches[i].sp) + 1; argv[j] = (char*)mallocz(k + 1, 1); strecpy(argv[j], argv[j] + k, matches[i].sp); } argv[j] = nil; return argv; } static char * do_action(char *action, int fd, Path *p) { char **argv = build_argv(fd, p->name); char *error = nil; int i; switch(fork()) { case 0 : exec(action, argv); error = "exec failed"; break; case -1 : error = "fork failed"; break; default : wait(); for(i = 0; i < nmatches+2; i++) free(argv[i]); free(argv); break; } return error; } static void fsopen(Req *r) { int fd; switch(r->ifcall.mode & 1) { // discard OTRUNC etc. case OREAD : fd = create(tmpnam(nil), ORDWR|ORCLOSE, 0600); if(fd < 1) { // assume fd 0 is taken ! respond(r, "/tmp/$file create failed"); return; } break; case OWRITE : fd = create(tmpnam(nil), ORDWR|ORCLOSE, 0600); if(fd < 1) { // assume fd 0 is taken ! respond(r, "/tmp/$file create failed"); return; } fd = -fd; break; default : respond(r, "permission denied"); return; } r->fid->aux = (void*)fd; Path *p = find_path(&r->fid->qid); char *error = nil; if(fd > 0) error = do_action("/bin/action-read", fd, p); respond(r, error); } static void remove_path(Path *p) { Path *pp; pp = find_prev_path(&p->qid); if(pp) pp->next = p->next; else root = nil; free(p->name); free(p); } static void fsclose(Fid *fid) { if(fid->aux) close(abs((int)fid->aux)); Path *p = find_path(&fid->qid); if(p && p->qid.path) // p *should* always be non null if(--p->qid.vers == 0) remove_path(p); } static void fsclunk(Fid *fid) { Path *p = find_path(&fid->qid); if((int)fid->aux < 0) { seek(abs((int)fid->aux), 0, 0); do_action("/bin/action-write", (int)fid->aux, p); } if(fid->aux) close(abs((int)fid->aux)); if(p && p->qid.path) // p *should* always be non null if(--p->qid.vers == 0) remove_path(p); } static void fsread(Req *r) { seek((int)r->fid->aux, r->ifcall.offset, 0); int k = read((int)r->fid->aux, r->ofcall.data, r->ifcall.count); if(k < 0) respond(r, "Read failed"); r->ofcall.count = k; respond(r, nil); } static void fswrite(Req *r) { seek(abs((int)r->fid->aux), r->ifcall.offset, 0); int k = write(abs((int)r->fid->aux), r->ifcall.data, r->ifcall.count); if(k < 0) respond(r, "Write failed"); r->ofcall.count = k; respond(r, nil); } Srv numsrv = { .attach= fsattach, .walk1= fswalk1, .open= fsopen, .read= fsread, .write= fswrite, .stat= fsstat, .destroyfid = fsclunk, }; static int num_matches(char *txt){ int i = 0; char *p; for(p = txt; p ; i++) { p = strchr(p, '('); if(p) p++; } return i ? i : 1; } extern int chatty9p; void main(int argc, char **argv) { char *mtpt, *service; char *reg; ARGBEGIN{ case 'D': chatty9p++; break; }ARGEND if(argc == 1) reg = argv[0]; else reg = ".*"; nmatches = num_matches(reg); freg = regcomp(reg); mtpt = "/n/actionfs"; service = "actionfs"; chdir("/tmp"); postmountsrv(&numsrv, service, mtpt, MREPL); exits(nil); } <!-- BEGIN TAIL --> </pre> </td></tr></table> </td></tr></table> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;"> <span style="font-size: 10pt"></span></p> <p style="margin-top: 0; margin-bottom: 0.50in"></p> <p style="margin-top: 0; margin-bottom: 0.33in"></p> <center><table border="0"><tr> <td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" /> </a></td> <td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" /> </a></td> <td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" /> </td> </tr></table></center> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <center> <span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span> </center> <p style="margin-top: 0; margin-bottom: 0.17in"></p> <center><font size=-1> <span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span> <span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span> <span style="font-size: 10pt">All Rights Reserved.</span> <br /> <span style="font-size: 10pt">Comments to</span> <span style="font-size: 10pt"><a href="mailto:webmaster@plan9.bell-labs.com">webmaster@plan9.bell-labs.com</a>.</span> </font></center> </body> </html>