From 897625ff9b8d718555baa408b05398ad178d986e Mon Sep 17 00:00:00 2001 From: fgergo Date: Sun, 7 Jan 2024 17:06:26 +0100 Subject: [PATCH] mntgen: import mntgen(4) from Plan 9 new file: man/man4/mntgen.4 new file: src/cmd/mntgen.c --- man/man4/mntgen.4 | 32 ++++++ src/cmd/mntgen.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 man/man4/mntgen.4 create mode 100644 src/cmd/mntgen.c diff --git a/man/man4/mntgen.4 b/man/man4/mntgen.4 new file mode 100644 index 00000000..af3b7568 --- /dev/null +++ b/man/man4/mntgen.4 @@ -0,0 +1,32 @@ +.TH MNTGEN 4 +.SH NAME +mntgen \- automatically generate mount points for file systems +.SH SYNOPSIS +.B mntgen +[ +.B -s +.I service +] +[ +.I mnt +] +.SH DESCRIPTION +.I Mntgen +mounts itself on +.I mnt +(default +.BR /n ) +after the current contents, +creating subdirectories on demand as they are accessed. +It is intended to supply mount points automatically. +.PP +The +.B -s +option causes +.I mntgen +to post a 9P +.I service \fR +file. +.SH SOURCE +.B \*9/src/cmd/mntgen.c + diff --git a/src/cmd/mntgen.c b/src/cmd/mntgen.c new file mode 100644 index 00000000..19483a79 --- /dev/null +++ b/src/cmd/mntgen.c @@ -0,0 +1,256 @@ +#include +#include +#include +#include +#include <9p.h> +#include +#include + +static void +usage(void) +{ + fprint(2, "mntgen [-s srvname] [mtpt]\n"); + threadexits("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; iifcall.mode != OREAD) + respond(r, "permission denied"); + else + respond(r, nil); +} + +static int +dirgen(int i, Dir *d, void* v) +{ + USED(v); + + 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* v) +{ + int i; + Tab *t; + vlong h; + + USED(v); + + 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; iqid.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* v, void* w) +{ + USED(v); + USED(w); + + 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 +}; + +int +threadmaybackground(void) +{ + return 1; +} + +void +threadmain(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(); + threadpostmountsrv(&fs, service, argc ? argv[0] : "/n", MAFTER); + threadexits(nil); +} +