<?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:
[email protected]">
[email protected]</a>.</span>
</font></center>
</body>
</html>