/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include <mp.h>#include <libsec.h> static voidusage(void){ fprint(2, "mntgen [-s srvname] [mtpt]\n"); exits("usage");} ulong time0; typedef struct Tab Tab;struct Tab{ char *name; vlong qid; ulong time; int ref;}; Tab *tab;int ntab;int mtab; static Tab*findtab(vlong path){ int i; for(i=0; i<ntab; i++) if(tab[i].qid == path) return &tab[i]; return nil;} static vlonghash(char *name){ vlong digest[MD5dlen / sizeof(vlong) + 1]; md5((uchar *)name, strlen(name), (uchar *)digest, nil); return digest[0] & ((1ULL<<48)-1);} static voidfsopen(Req *r){ if(r->ifcall.mode != OREAD) respond(r, "permission denied"); else respond(r, nil);} static intdirgen(int i, Dir *d, void*){ if(i >= ntab) return -1; memset(d, 0, sizeof *d); d->qid.type = QTDIR; d->uid = estrdup9p("sys"); d->gid = estrdup9p("sys"); d->mode = DMDIR|0555; d->length = 0; if(i == -1){ d->name = estrdup9p("/"); d->atime = d->mtime = time0; }else{ d->qid.path = tab[i].qid; d->name = estrdup9p(tab[i].name); d->atime = d->mtime = tab[i].time; } return 0;} static voidfsread(Req *r){ if(r->fid->qid.path == 0) dirread9p(r, dirgen, nil); else r->ofcall.count = 0; respond(r, nil);} static voidfsstat(Req *r){ Tab *t; vlong qid; qid = r->fid->qid.path; if(qid == 0) dirgen(-1, &r->d, nil); else{ if((t = findtab(qid)) == nil){ respond(r, "path not found (???)"); return; } dirgen(t-tab, &r->d, nil); } respond(r, nil);} static char*fswalk1(Fid *fid, char *name, void*){ int i; Tab *t; vlong h; if(fid->qid.path != 0){ /* nothing in child directory */ if(strcmp(name, "..") == 0){ if((t = findtab(fid->qid.path)) != nil) t->ref--; fid->qid.path = 0; return nil; } return "path not found"; } /* root */ if(strcmp(name, "..") == 0) return nil; for(i=0; i<ntab; i++) if(strcmp(tab[i].name, name) == 0){ tab[i].ref++; fid->qid.path = tab[i].qid; return nil; } h = hash(name); if(findtab(h) != nil) return "hash collision"; /* create it */ if(ntab == mtab){ if(mtab == 0) mtab = 16; else mtab *= 2; tab = erealloc9p(tab, sizeof(tab[0])*mtab); } tab[ntab].qid = h; fid->qid.path = tab[ntab].qid; tab[ntab].name = estrdup9p(name); tab[ntab].time = time(0); tab[ntab].ref = 1; ntab++; return nil;} static char*fsclone(Fid *fid, Fid*, void*){ Tab *t; if((t = findtab(fid->qid.path)) != nil) t->ref++; return nil;} static voidfswalk(Req *r){ walkandclone(r, fswalk1, fsclone, nil);} static voidfsclunk(Fid *fid){ Tab *t; vlong qid; qid = fid->qid.path; if(qid == 0) return; if((t = findtab(qid)) == nil){ fprint(2, "warning: cannot find %llux\n", qid); return; } if(--t->ref == 0){ free(t->name); tab[t-tab] = tab[--ntab]; }else if(t->ref < 0) fprint(2, "warning: negative ref count for %s\n", t->name);} static voidfsattach(Req *r){ char *spec; spec = r->ifcall.aname; if(spec && spec[0]){ respond(r, "invalid attach specifier"); return; } r->ofcall.qid = (Qid){0, 0, QTDIR}; r->fid->qid = r->ofcall.qid; respond(r, nil);} Srv fs={.attach= fsattach,.open= fsopen,.read= fsread,.stat= fsstat,.walk= fswalk,.destroyfid= fsclunk}; voidmain(int argc, char **argv){ char *service; time0 = time(0); service = nil; ARGBEGIN{ case 'D': chatty9p++; break; case 's': service = EARGF(usage()); break; default: usage(); }ARGEND if(argc > 1) usage(); postmountsrv(&fs, service, argc ? argv[0] : "/n", MAFTER); exits(nil);}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <mp.h>
#include <libsec.h>
static void
usage(void)
{
fprint(2, "mntgen [-s srvname] [mtpt]\n");
exits("usage");
}
ulong time0;
typedef struct Tab Tab;
struct Tab
{
char *name;
vlong qid;
ulong time;
int ref;
};
Tab *tab;
int ntab;
int mtab;
static Tab*
findtab(vlong path)
{
int i;
for(i=0; i<ntab; i++)
if(tab[i].qid == path)
return &tab[i];
return nil;
}
static vlong
hash(char *name)
{
vlong digest[MD5dlen / sizeof(vlong) + 1];
md5((uchar *)name, strlen(name), (uchar *)digest, nil);
return digest[0] & ((1ULL<<48)-1);
}
static void
fsopen(Req *r)
{
if(r->ifcall.mode != OREAD)
respond(r, "permission denied");
else
respond(r, nil);
}
static int
dirgen(int i, Dir *d, void*)
{
if(i >= ntab)
return -1;
memset(d, 0, sizeof *d);
d->qid.type = QTDIR;
d->uid = estrdup9p("sys");
d->gid = estrdup9p("sys");
d->mode = DMDIR|0555;
d->length = 0;
if(i == -1){
d->name = estrdup9p("/");
d->atime = d->mtime = time0;
}else{
d->qid.path = tab[i].qid;
d->name = estrdup9p(tab[i].name);
d->atime = d->mtime = tab[i].time;
}
return 0;
}
static void
fsread(Req *r)
{
if(r->fid->qid.path == 0)
dirread9p(r, dirgen, nil);
else
r->ofcall.count = 0;
respond(r, nil);
}
static void
fsstat(Req *r)
{
Tab *t;
vlong qid;
qid = r->fid->qid.path;
if(qid == 0)
dirgen(-1, &r->d, nil);
else{
if((t = findtab(qid)) == nil){
respond(r, "path not found (???)");
return;
}
dirgen(t-tab, &r->d, nil);
}
respond(r, nil);
}
static char*
fswalk1(Fid *fid, char *name, void*)
{
int i;
Tab *t;
vlong h;
if(fid->qid.path != 0){
/* nothing in child directory */
if(strcmp(name, "..") == 0){
if((t = findtab(fid->qid.path)) != nil)
t->ref--;
fid->qid.path = 0;
return nil;
}
return "path not found";
}
/* root */
if(strcmp(name, "..") == 0)
return nil;
for(i=0; i<ntab; i++)
if(strcmp(tab[i].name, name) == 0){
tab[i].ref++;
fid->qid.path = tab[i].qid;
return nil;
}
h = hash(name);
if(findtab(h) != nil)
return "hash collision";
/* create it */
if(ntab == mtab){
if(mtab == 0)
mtab = 16;
else
mtab *= 2;
tab = erealloc9p(tab, sizeof(tab[0])*mtab);
}
tab[ntab].qid = h;
fid->qid.path = tab[ntab].qid;
tab[ntab].name = estrdup9p(name);
tab[ntab].time = time(0);
tab[ntab].ref = 1;
ntab++;
return nil;
}
static char*
fsclone(Fid *fid, Fid*, void*)
{
Tab *t;
if((t = findtab(fid->qid.path)) != nil)
t->ref++;
return nil;
}
static void
fswalk(Req *r)
{
walkandclone(r, fswalk1, fsclone, nil);
}
static void
fsclunk(Fid *fid)
{
Tab *t;
vlong qid;
qid = fid->qid.path;
if(qid == 0)
return;
if((t = findtab(qid)) == nil){
fprint(2, "warning: cannot find %llux\n", qid);
return;
}
if(--t->ref == 0){
free(t->name);
tab[t-tab] = tab[--ntab];
}else if(t->ref < 0)
fprint(2, "warning: negative ref count for %s\n", t->name);
}
static void
fsattach(Req *r)
{
char *spec;
spec = r->ifcall.aname;
if(spec && spec[0]){
respond(r, "invalid attach specifier");
return;
}
r->ofcall.qid = (Qid){0, 0, QTDIR};
r->fid->qid = r->ofcall.qid;
respond(r, nil);
}
Srv fs=
{
.attach= fsattach,
.open= fsopen,
.read= fsread,
.stat= fsstat,
.walk= fswalk,
.destroyfid= fsclunk
};
void
main(int argc, char **argv)
{
char *service;
time0 = time(0);
service = nil;
ARGBEGIN{
case 'D':
chatty9p++;
break;
case 's':
service = EARGF(usage());
break;
default:
usage();
}ARGEND
if(argc > 1)
usage();
postmountsrv(&fs, service, argc ? argv[0] : "/n", MAFTER);
exits(nil);
}