19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <String.h>
59a747e4fSDavid du Colombier #include <thread.h>
69a747e4fSDavid du Colombier #include "wiki.h"
79a747e4fSDavid du Colombier
89a747e4fSDavid du Colombier #include <auth.h>
99a747e4fSDavid du Colombier #include <fcall.h>
109a747e4fSDavid du Colombier #include <9p.h>
119a747e4fSDavid du Colombier
129a747e4fSDavid du Colombier enum {
139a747e4fSDavid du Colombier Qindexhtml,
149a747e4fSDavid du Colombier Qindextxt,
159a747e4fSDavid du Colombier Qraw,
169a747e4fSDavid du Colombier Qhistoryhtml,
179a747e4fSDavid du Colombier Qhistorytxt,
189a747e4fSDavid du Colombier Qdiffhtml,
199a747e4fSDavid du Colombier Qedithtml,
209a747e4fSDavid du Colombier Qwerrorhtml,
219a747e4fSDavid du Colombier Qwerrortxt,
22b7327ca2SDavid du Colombier Qhttplogin,
239a747e4fSDavid du Colombier Nfile,
249a747e4fSDavid du Colombier };
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier static char *filelist[] = {
279a747e4fSDavid du Colombier "index.html",
289a747e4fSDavid du Colombier "index.txt",
299a747e4fSDavid du Colombier "current",
309a747e4fSDavid du Colombier "history.html",
319a747e4fSDavid du Colombier "history.txt",
329a747e4fSDavid du Colombier "diff.html",
339a747e4fSDavid du Colombier "edit.html",
349a747e4fSDavid du Colombier "werror.html",
359a747e4fSDavid du Colombier "werror.txt",
36b7327ca2SDavid du Colombier ".httplogin",
379a747e4fSDavid du Colombier };
389a747e4fSDavid du Colombier
399a747e4fSDavid du Colombier static int needhist[Nfile] = {
409a747e4fSDavid du Colombier [Qhistoryhtml] 1,
419a747e4fSDavid du Colombier [Qhistorytxt] 1,
429a747e4fSDavid du Colombier [Qdiffhtml] 1,
439a747e4fSDavid du Colombier };
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier /*
469a747e4fSDavid du Colombier * The qids are <8-bit type><16-bit page number><16-bit page version><8-bit file index>.
479a747e4fSDavid du Colombier */
489a747e4fSDavid du Colombier enum { /* <8-bit type> */
499a747e4fSDavid du Colombier Droot = 1,
509a747e4fSDavid du Colombier D1st,
519a747e4fSDavid du Colombier D2nd,
529a747e4fSDavid du Colombier Fnew,
539a747e4fSDavid du Colombier Fmap,
549a747e4fSDavid du Colombier F1st,
559a747e4fSDavid du Colombier F2nd,
569a747e4fSDavid du Colombier };
579a747e4fSDavid du Colombier
589a747e4fSDavid du Colombier uvlong
mkqid(int type,int num,int vers,int file)599a747e4fSDavid du Colombier mkqid(int type, int num, int vers, int file)
609a747e4fSDavid du Colombier {
619a747e4fSDavid du Colombier return ((uvlong)type<<40) | ((uvlong)num<<24) | (vers<<8) | file;
629a747e4fSDavid du Colombier }
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier int
qidtype(uvlong path)659a747e4fSDavid du Colombier qidtype(uvlong path)
669a747e4fSDavid du Colombier {
679a747e4fSDavid du Colombier return (path>>40)&0xFF;
689a747e4fSDavid du Colombier }
699a747e4fSDavid du Colombier
709a747e4fSDavid du Colombier int
qidnum(uvlong path)719a747e4fSDavid du Colombier qidnum(uvlong path)
729a747e4fSDavid du Colombier {
739a747e4fSDavid du Colombier return (path>>24)&0xFFFF;
749a747e4fSDavid du Colombier }
759a747e4fSDavid du Colombier
769a747e4fSDavid du Colombier int
qidvers(uvlong path)779a747e4fSDavid du Colombier qidvers(uvlong path)
789a747e4fSDavid du Colombier {
799a747e4fSDavid du Colombier return (path>>8)&0xFFFF;
809a747e4fSDavid du Colombier }
819a747e4fSDavid du Colombier
829a747e4fSDavid du Colombier int
qidfile(uvlong path)839a747e4fSDavid du Colombier qidfile(uvlong path)
849a747e4fSDavid du Colombier {
859a747e4fSDavid du Colombier return path&0xFF;
869a747e4fSDavid du Colombier }
879a747e4fSDavid du Colombier
889a747e4fSDavid du Colombier typedef struct Aux Aux;
899a747e4fSDavid du Colombier struct Aux {
90af2e6ba6SDavid du Colombier String *name;
919a747e4fSDavid du Colombier Whist *w;
929a747e4fSDavid du Colombier int n;
939a747e4fSDavid du Colombier ulong t;
949a747e4fSDavid du Colombier String *s;
959a747e4fSDavid du Colombier Map *map;
969a747e4fSDavid du Colombier };
979a747e4fSDavid du Colombier
989a747e4fSDavid du Colombier static void
fsattach(Req * r)999a747e4fSDavid du Colombier fsattach(Req *r)
1009a747e4fSDavid du Colombier {
1019a747e4fSDavid du Colombier Aux *a;
1029a747e4fSDavid du Colombier
1039a747e4fSDavid du Colombier if(r->ifcall.aname && r->ifcall.aname[0]){
1049a747e4fSDavid du Colombier respond(r, "invalid attach specifier");
1059a747e4fSDavid du Colombier return;
1069a747e4fSDavid du Colombier }
1079a747e4fSDavid du Colombier
1089a747e4fSDavid du Colombier a = emalloc(sizeof(Aux));
1099a747e4fSDavid du Colombier r->fid->aux = a;
110af2e6ba6SDavid du Colombier a->name = s_copy(r->ifcall.uname);
1119a747e4fSDavid du Colombier
112690670dcSDavid du Colombier r->ofcall.qid = (Qid){mkqid(Droot, 0, 0, 0), 0, QTDIR};
1139a747e4fSDavid du Colombier r->fid->qid = r->ofcall.qid;
1149a747e4fSDavid du Colombier respond(r, nil);
1159a747e4fSDavid du Colombier }
1169a747e4fSDavid du Colombier
117b7327ca2SDavid du Colombier static String *
httplogin(void)118b7327ca2SDavid du Colombier httplogin(void)
119b7327ca2SDavid du Colombier {
120b7327ca2SDavid du Colombier String *s=s_new();
121b7327ca2SDavid du Colombier Biobuf *b;
122b7327ca2SDavid du Colombier
123b7327ca2SDavid du Colombier if((b = wBopen(".httplogin", OREAD)) == nil)
124b7327ca2SDavid du Colombier goto Return;
125b7327ca2SDavid du Colombier
126b7327ca2SDavid du Colombier while(s_read(b, s, Bsize) > 0)
127b7327ca2SDavid du Colombier ;
128b7327ca2SDavid du Colombier Bterm(b);
129b7327ca2SDavid du Colombier
130b7327ca2SDavid du Colombier Return:
131b7327ca2SDavid du Colombier return s;
132b7327ca2SDavid du Colombier }
133b7327ca2SDavid du Colombier
1349a747e4fSDavid du Colombier static char*
fswalk1(Fid * fid,char * name,Qid * qid)1359a747e4fSDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid)
1369a747e4fSDavid du Colombier {
1379a747e4fSDavid du Colombier char *q;
1389a747e4fSDavid du Colombier int i, isdotdot, n, t;
1399a747e4fSDavid du Colombier uvlong path;
1409a747e4fSDavid du Colombier Aux *a;
1419a747e4fSDavid du Colombier Whist *wh;
1429a747e4fSDavid du Colombier String *s;
1439a747e4fSDavid du Colombier
1449a747e4fSDavid du Colombier isdotdot = strcmp(name, "..")==0;
1459a747e4fSDavid du Colombier n = strtoul(name, &q, 10);
1469a747e4fSDavid du Colombier path = fid->qid.path;
1479a747e4fSDavid du Colombier a = fid->aux;
1489a747e4fSDavid du Colombier
1499a747e4fSDavid du Colombier switch(qidtype(path)){
1509a747e4fSDavid du Colombier case 0:
1519a747e4fSDavid du Colombier return "wikifs: bad path in server (bug)";
1529a747e4fSDavid du Colombier
1539a747e4fSDavid du Colombier case Droot:
1549a747e4fSDavid du Colombier if(isdotdot){
1559a747e4fSDavid du Colombier *qid = fid->qid;
1569a747e4fSDavid du Colombier return nil;
1579a747e4fSDavid du Colombier }
1589a747e4fSDavid du Colombier if(strcmp(name, "new")==0){
1599a747e4fSDavid du Colombier *qid = (Qid){mkqid(Fnew, 0, 0, 0), 0, 0};
1609a747e4fSDavid du Colombier return nil;
1619a747e4fSDavid du Colombier }
1629a747e4fSDavid du Colombier if(strcmp(name, "map")==0){
1639a747e4fSDavid du Colombier *qid = (Qid){mkqid(Fmap, 0, 0, 0), 0, 0};
1649a747e4fSDavid du Colombier return nil;
1659a747e4fSDavid du Colombier }
1669a747e4fSDavid du Colombier if((*q!='\0' || (wh=getcurrent(n))==nil)
1679a747e4fSDavid du Colombier && (wh=getcurrentbyname(name))==nil)
1689a747e4fSDavid du Colombier return "file does not exist";
1699a747e4fSDavid du Colombier *qid = (Qid){mkqid(D1st, wh->n, 0, 0), wh->doc->time, QTDIR};
1709a747e4fSDavid du Colombier a->w = wh;
1719a747e4fSDavid du Colombier return nil;
1729a747e4fSDavid du Colombier
1739a747e4fSDavid du Colombier case D1st:
1749a747e4fSDavid du Colombier if(isdotdot){
1759a747e4fSDavid du Colombier *qid = (Qid){mkqid(Droot, 0, 0, 0), 0, QTDIR};
1769a747e4fSDavid du Colombier return nil;
1779a747e4fSDavid du Colombier }
1789a747e4fSDavid du Colombier
1799a747e4fSDavid du Colombier /* handle history directories */
1809a747e4fSDavid du Colombier if(*q == '\0'){
1819a747e4fSDavid du Colombier if((wh = gethistory(qidnum(path))) == nil)
1829a747e4fSDavid du Colombier return "file does not exist";
1839a747e4fSDavid du Colombier for(i=0; i<wh->ndoc; i++)
1849a747e4fSDavid du Colombier if(wh->doc[i].time == n)
1859a747e4fSDavid du Colombier break;
1869a747e4fSDavid du Colombier if(i==wh->ndoc){
1879a747e4fSDavid du Colombier closewhist(wh);
1889a747e4fSDavid du Colombier return "file does not exist";
1899a747e4fSDavid du Colombier }
1909a747e4fSDavid du Colombier closewhist(a->w);
1919a747e4fSDavid du Colombier a->w = wh;
1929a747e4fSDavid du Colombier a->n = i;
1939a747e4fSDavid du Colombier *qid = (Qid){mkqid(D2nd, qidnum(path), i, 0), wh->doc[i].time, QTDIR};
1949a747e4fSDavid du Colombier return nil;
1959a747e4fSDavid du Colombier }
1969a747e4fSDavid du Colombier
1979a747e4fSDavid du Colombier /* handle files other than index */
1989a747e4fSDavid du Colombier for(i=0; i<nelem(filelist); i++){
1999a747e4fSDavid du Colombier if(strcmp(name, filelist[i])==0){
2009a747e4fSDavid du Colombier if(needhist[i]){
2019a747e4fSDavid du Colombier if((wh = gethistory(qidnum(path))) == nil)
2029a747e4fSDavid du Colombier return "file does not exist";
2039a747e4fSDavid du Colombier closewhist(a->w);
2049a747e4fSDavid du Colombier a->w = wh;
2059a747e4fSDavid du Colombier }
2069a747e4fSDavid du Colombier *qid = (Qid){mkqid(F1st, qidnum(path), 0, i), a->w->doc->time, 0};
2079a747e4fSDavid du Colombier goto Gotfile;
2089a747e4fSDavid du Colombier }
2099a747e4fSDavid du Colombier }
2109a747e4fSDavid du Colombier return "file does not exist";
2119a747e4fSDavid du Colombier
2129a747e4fSDavid du Colombier case D2nd:
2139a747e4fSDavid du Colombier if(isdotdot){
2149a747e4fSDavid du Colombier /*
2159a747e4fSDavid du Colombier * Can't use a->w[a->ndoc-1] because that
2169a747e4fSDavid du Colombier * might be a failed write rather than the real one.
2179a747e4fSDavid du Colombier */
2189a747e4fSDavid du Colombier *qid = (Qid){mkqid(D1st, qidnum(path), 0, 0), 0, QTDIR};
2199a747e4fSDavid du Colombier if((wh = getcurrent(qidnum(path))) == nil)
2209a747e4fSDavid du Colombier return "file does not exist";
2219a747e4fSDavid du Colombier closewhist(a->w);
2229a747e4fSDavid du Colombier a->w = wh;
2239a747e4fSDavid du Colombier a->n = 0;
2249a747e4fSDavid du Colombier return nil;
2259a747e4fSDavid du Colombier }
2269a747e4fSDavid du Colombier for(i=0; i<=Qraw; i++){
2279a747e4fSDavid du Colombier if(strcmp(name, filelist[i])==0){
2289a747e4fSDavid du Colombier *qid = (Qid){mkqid(F2nd, qidnum(path), qidvers(path), i), a->w->doc->time, 0};
2299a747e4fSDavid du Colombier goto Gotfile;
2309a747e4fSDavid du Colombier }
2319a747e4fSDavid du Colombier }
2329a747e4fSDavid du Colombier return "file does not exist";
2339a747e4fSDavid du Colombier
2349a747e4fSDavid du Colombier default:
2359a747e4fSDavid du Colombier return "bad programming";
2369a747e4fSDavid du Colombier }
237b85a8364SDavid du Colombier /* not reached */
2389a747e4fSDavid du Colombier
2399a747e4fSDavid du Colombier Gotfile:
2409a747e4fSDavid du Colombier t = qidtype(qid->path);
2419a747e4fSDavid du Colombier switch(qidfile(qid->path)){
2429a747e4fSDavid du Colombier case Qindexhtml:
2439a747e4fSDavid du Colombier s = tohtml(a->w, a->w->doc+a->n,
2449a747e4fSDavid du Colombier t==F1st? Tpage : Toldpage);
2459a747e4fSDavid du Colombier break;
2469a747e4fSDavid du Colombier case Qindextxt:
2479a747e4fSDavid du Colombier s = totext(a->w, a->w->doc+a->n,
2489a747e4fSDavid du Colombier t==F1st? Tpage : Toldpage);
2499a747e4fSDavid du Colombier break;
2509a747e4fSDavid du Colombier case Qraw:
2519a747e4fSDavid du Colombier s = s_copy(a->w->title);
2529a747e4fSDavid du Colombier s = s_append(s, "\n");
2539a747e4fSDavid du Colombier s = doctext(s, &a->w->doc[a->n]);
2549a747e4fSDavid du Colombier break;
2559a747e4fSDavid du Colombier case Qhistoryhtml:
2569a747e4fSDavid du Colombier s = tohtml(a->w, a->w->doc+a->n, Thistory);
2579a747e4fSDavid du Colombier break;
2589a747e4fSDavid du Colombier case Qhistorytxt:
2599a747e4fSDavid du Colombier s = totext(a->w, a->w->doc+a->n, Thistory);
2609a747e4fSDavid du Colombier break;
2619a747e4fSDavid du Colombier case Qdiffhtml:
2629a747e4fSDavid du Colombier s = tohtml(a->w, a->w->doc+a->n, Tdiff);
2639a747e4fSDavid du Colombier break;
2649a747e4fSDavid du Colombier case Qedithtml:
2659a747e4fSDavid du Colombier s = tohtml(a->w, a->w->doc+a->n, Tedit);
2669a747e4fSDavid du Colombier break;
2679a747e4fSDavid du Colombier case Qwerrorhtml:
2689a747e4fSDavid du Colombier s = tohtml(a->w, a->w->doc+a->n, Twerror);
2699a747e4fSDavid du Colombier break;
2709a747e4fSDavid du Colombier case Qwerrortxt:
2719a747e4fSDavid du Colombier s = totext(a->w, a->w->doc+a->n, Twerror);
2729a747e4fSDavid du Colombier break;
273b7327ca2SDavid du Colombier case Qhttplogin:
274b7327ca2SDavid du Colombier s = httplogin();
275b7327ca2SDavid du Colombier break;
2769a747e4fSDavid du Colombier default:
2779a747e4fSDavid du Colombier return "internal error";
2789a747e4fSDavid du Colombier }
2799a747e4fSDavid du Colombier a->s = s;
2809a747e4fSDavid du Colombier return nil;
2819a747e4fSDavid du Colombier }
2829a747e4fSDavid du Colombier
2839a747e4fSDavid du Colombier static void
fsopen(Req * r)2849a747e4fSDavid du Colombier fsopen(Req *r)
2859a747e4fSDavid du Colombier {
2869a747e4fSDavid du Colombier int t;
2879a747e4fSDavid du Colombier uvlong path;
2889a747e4fSDavid du Colombier Aux *a;
2899a747e4fSDavid du Colombier Fid *fid;
2909a747e4fSDavid du Colombier Whist *wh;
2919a747e4fSDavid du Colombier
2929a747e4fSDavid du Colombier fid = r->fid;
2939a747e4fSDavid du Colombier path = fid->qid.path;
2949a747e4fSDavid du Colombier t = qidtype(fid->qid.path);
2959a747e4fSDavid du Colombier if((r->ifcall.mode != OREAD && t != Fnew && t != Fmap)
2969a747e4fSDavid du Colombier || (r->ifcall.mode&ORCLOSE)){
2979a747e4fSDavid du Colombier respond(r, "permission denied");
2989a747e4fSDavid du Colombier return;
2999a747e4fSDavid du Colombier }
3009a747e4fSDavid du Colombier
3019a747e4fSDavid du Colombier a = fid->aux;
3029a747e4fSDavid du Colombier switch(t){
3039a747e4fSDavid du Colombier case Droot:
3049a747e4fSDavid du Colombier currentmap(0);
3059a747e4fSDavid du Colombier rlock(&maplock);
3069a747e4fSDavid du Colombier a->map = map;
3079a747e4fSDavid du Colombier incref(map);
3089a747e4fSDavid du Colombier runlock(&maplock);
3099a747e4fSDavid du Colombier respond(r, nil);
3109a747e4fSDavid du Colombier break;
3119a747e4fSDavid du Colombier
3129a747e4fSDavid du Colombier case D1st:
3139a747e4fSDavid du Colombier if((wh = gethistory(qidnum(path))) == nil){
3149a747e4fSDavid du Colombier respond(r, "file does not exist");
3159a747e4fSDavid du Colombier return;
3169a747e4fSDavid du Colombier }
3179a747e4fSDavid du Colombier closewhist(a->w);
3189a747e4fSDavid du Colombier a->w = wh;
3199a747e4fSDavid du Colombier a->n = a->w->ndoc-1;
3209a747e4fSDavid du Colombier r->ofcall.qid.vers = wh->doc[a->n].time;
3219a747e4fSDavid du Colombier r->fid->qid = r->ofcall.qid;
3229a747e4fSDavid du Colombier respond(r, nil);
3239a747e4fSDavid du Colombier break;
3249a747e4fSDavid du Colombier
3259a747e4fSDavid du Colombier case D2nd:
3269a747e4fSDavid du Colombier respond(r, nil);
3279a747e4fSDavid du Colombier break;
3289a747e4fSDavid du Colombier
3299a747e4fSDavid du Colombier case Fnew:
3309a747e4fSDavid du Colombier a->s = s_copy("");
3319a747e4fSDavid du Colombier respond(r, nil);
3329a747e4fSDavid du Colombier break;
3339a747e4fSDavid du Colombier
3349a747e4fSDavid du Colombier case Fmap:
3359a747e4fSDavid du Colombier case F1st:
3369a747e4fSDavid du Colombier case F2nd:
3379a747e4fSDavid du Colombier respond(r, nil);
3389a747e4fSDavid du Colombier break;
3399a747e4fSDavid du Colombier
3409a747e4fSDavid du Colombier default:
3419a747e4fSDavid du Colombier respond(r, "programmer error");
3429a747e4fSDavid du Colombier break;
3439a747e4fSDavid du Colombier }
3449a747e4fSDavid du Colombier }
3459a747e4fSDavid du Colombier
3469a747e4fSDavid du Colombier static char*
fsclone(Fid * old,Fid * new)3479a747e4fSDavid du Colombier fsclone(Fid *old, Fid *new)
3489a747e4fSDavid du Colombier {
3499a747e4fSDavid du Colombier Aux *a;
3509a747e4fSDavid du Colombier
3519a747e4fSDavid du Colombier a = emalloc(sizeof(*a));
3529a747e4fSDavid du Colombier *a = *(Aux*)old->aux;
3539a747e4fSDavid du Colombier if(a->s)
3549a747e4fSDavid du Colombier s_incref(a->s);
3559a747e4fSDavid du Colombier if(a->w)
3569a747e4fSDavid du Colombier incref(a->w);
3579a747e4fSDavid du Colombier if(a->map)
3589a747e4fSDavid du Colombier incref(a->map);
359af2e6ba6SDavid du Colombier if(a->name)
360af2e6ba6SDavid du Colombier s_incref(a->name);
3619a747e4fSDavid du Colombier new->aux = a;
3629a747e4fSDavid du Colombier new->qid = old->qid;
3639a747e4fSDavid du Colombier
3649a747e4fSDavid du Colombier return nil;
3659a747e4fSDavid du Colombier }
3669a747e4fSDavid du Colombier
3679a747e4fSDavid du Colombier static void
fsdestroyfid(Fid * fid)3689a747e4fSDavid du Colombier fsdestroyfid(Fid *fid)
3699a747e4fSDavid du Colombier {
3709a747e4fSDavid du Colombier Aux *a;
3719a747e4fSDavid du Colombier
3729a747e4fSDavid du Colombier a = fid->aux;
3739a747e4fSDavid du Colombier if(a==nil)
3749a747e4fSDavid du Colombier return;
3759a747e4fSDavid du Colombier
376af2e6ba6SDavid du Colombier if(a->name)
377af2e6ba6SDavid du Colombier s_free(a->name);
3789a747e4fSDavid du Colombier if(a->map)
3799a747e4fSDavid du Colombier closemap(a->map);
3809a747e4fSDavid du Colombier if(a->s)
3819a747e4fSDavid du Colombier s_free(a->s);
3829a747e4fSDavid du Colombier if(a->w)
3839a747e4fSDavid du Colombier closewhist(a->w);
3849a747e4fSDavid du Colombier free(a);
3859a747e4fSDavid du Colombier fid->aux = nil;
3869a747e4fSDavid du Colombier }
3879a747e4fSDavid du Colombier
3889a747e4fSDavid du Colombier static void
fillstat(Dir * d,uvlong path,ulong tm,ulong length)3899a747e4fSDavid du Colombier fillstat(Dir *d, uvlong path, ulong tm, ulong length)
3909a747e4fSDavid du Colombier {
3919a747e4fSDavid du Colombier char tmp[32], *p;
3929a747e4fSDavid du Colombier int type;
3939a747e4fSDavid du Colombier
3949a747e4fSDavid du Colombier memset(d, 0, sizeof(Dir));
3959a747e4fSDavid du Colombier d->uid = estrdup9p("wiki");
3969a747e4fSDavid du Colombier d->gid = estrdup9p("wiki");
3979a747e4fSDavid du Colombier
3989a747e4fSDavid du Colombier switch(qidtype(path)){
3999a747e4fSDavid du Colombier case Droot:
4009a747e4fSDavid du Colombier case D1st:
4019a747e4fSDavid du Colombier case D2nd:
4029a747e4fSDavid du Colombier type = QTDIR;
4039a747e4fSDavid du Colombier break;
4049a747e4fSDavid du Colombier default:
4059a747e4fSDavid du Colombier type = 0;
4069a747e4fSDavid du Colombier break;
4079a747e4fSDavid du Colombier }
4089a747e4fSDavid du Colombier d->qid = (Qid){path, tm, type};
4099a747e4fSDavid du Colombier
4109a747e4fSDavid du Colombier d->atime = d->mtime = tm;
4119a747e4fSDavid du Colombier d->length = length;
4129a747e4fSDavid du Colombier if(qidfile(path) == Qedithtml)
4139a747e4fSDavid du Colombier d->atime = d->mtime = time(0);
4149a747e4fSDavid du Colombier
4159a747e4fSDavid du Colombier switch(qidtype(path)){
4169a747e4fSDavid du Colombier case Droot:
4179a747e4fSDavid du Colombier d->name = estrdup("/");
4189a747e4fSDavid du Colombier d->mode = DMDIR|0555;
4199a747e4fSDavid du Colombier break;
4209a747e4fSDavid du Colombier
4219a747e4fSDavid du Colombier case D1st:
4229a747e4fSDavid du Colombier d->name = numtoname(qidnum(path));
4239a747e4fSDavid du Colombier if(d->name == nil)
4249a747e4fSDavid du Colombier d->name = estrdup("<dead>");
4259a747e4fSDavid du Colombier for(p=d->name; *p; p++)
4269a747e4fSDavid du Colombier if(*p==' ')
4279a747e4fSDavid du Colombier *p = '_';
4289a747e4fSDavid du Colombier d->mode = DMDIR|0555;
4299a747e4fSDavid du Colombier break;
4309a747e4fSDavid du Colombier
4319a747e4fSDavid du Colombier case D2nd:
4329a747e4fSDavid du Colombier snprint(tmp, sizeof tmp, "%lud", tm);
4339a747e4fSDavid du Colombier d->name = estrdup(tmp);
4349a747e4fSDavid du Colombier d->mode = DMDIR|0555;
4359a747e4fSDavid du Colombier break;
4369a747e4fSDavid du Colombier
4379a747e4fSDavid du Colombier case Fmap:
4389a747e4fSDavid du Colombier d->name = estrdup("map");
4399a747e4fSDavid du Colombier d->mode = 0666;
4409a747e4fSDavid du Colombier break;
4419a747e4fSDavid du Colombier
4429a747e4fSDavid du Colombier case Fnew:
4439a747e4fSDavid du Colombier d->name = estrdup("new");
4449a747e4fSDavid du Colombier d->mode = 0666;
4459a747e4fSDavid du Colombier break;
4469a747e4fSDavid du Colombier
4479a747e4fSDavid du Colombier case F1st:
4489a747e4fSDavid du Colombier d->name = estrdup(filelist[qidfile(path)]);
4499a747e4fSDavid du Colombier d->mode = 0444;
4509a747e4fSDavid du Colombier break;
4519a747e4fSDavid du Colombier
4529a747e4fSDavid du Colombier case F2nd:
4539a747e4fSDavid du Colombier d->name = estrdup(filelist[qidfile(path)]);
4549a747e4fSDavid du Colombier d->mode = 0444;
4559a747e4fSDavid du Colombier break;
4569a747e4fSDavid du Colombier
4579a747e4fSDavid du Colombier default:
4589a747e4fSDavid du Colombier print("bad qid path 0x%.8llux\n", path);
4599a747e4fSDavid du Colombier break;
4609a747e4fSDavid du Colombier }
4619a747e4fSDavid du Colombier }
4629a747e4fSDavid du Colombier
4639a747e4fSDavid du Colombier static void
fsstat(Req * r)4649a747e4fSDavid du Colombier fsstat(Req *r)
4659a747e4fSDavid du Colombier {
4669a747e4fSDavid du Colombier Aux *a;
4679a747e4fSDavid du Colombier Fid *fid;
4689a747e4fSDavid du Colombier ulong t;
4699a747e4fSDavid du Colombier
4709a747e4fSDavid du Colombier t = 0;
4719a747e4fSDavid du Colombier fid = r->fid;
4729a747e4fSDavid du Colombier if((a = fid->aux) && a->w)
4739a747e4fSDavid du Colombier t = a->w->doc[a->n].time;
4749a747e4fSDavid du Colombier
4759a747e4fSDavid du Colombier fillstat(&r->d, fid->qid.path, t, a->s ? s_len(a->s) : 0);
4769a747e4fSDavid du Colombier respond(r, nil);
4779a747e4fSDavid du Colombier }
4789a747e4fSDavid du Colombier
4799a747e4fSDavid du Colombier typedef struct Bogus Bogus;
4809a747e4fSDavid du Colombier struct Bogus {
4819a747e4fSDavid du Colombier uvlong path;
4829a747e4fSDavid du Colombier Aux *a;
4839a747e4fSDavid du Colombier };
4849a747e4fSDavid du Colombier
4859a747e4fSDavid du Colombier static int
rootgen(int i,Dir * d,void * aux)4869a747e4fSDavid du Colombier rootgen(int i, Dir *d, void *aux)
4879a747e4fSDavid du Colombier {
4889a747e4fSDavid du Colombier Aux *a;
4899a747e4fSDavid du Colombier Bogus *b;
4909a747e4fSDavid du Colombier
4919a747e4fSDavid du Colombier b = aux;
4929a747e4fSDavid du Colombier a = b->a;
4939a747e4fSDavid du Colombier switch(i){
4949a747e4fSDavid du Colombier case 0: /* new */
4959a747e4fSDavid du Colombier fillstat(d, mkqid(Fnew, 0, 0, 0), a->map->t, 0);
4969a747e4fSDavid du Colombier return 0;
4979a747e4fSDavid du Colombier case 1: /* map */
4989a747e4fSDavid du Colombier fillstat(d, mkqid(Fmap, 0, 0, 0), a->map->t, 0);
4999a747e4fSDavid du Colombier return 0;
5009a747e4fSDavid du Colombier default: /* first-level directory */
5019a747e4fSDavid du Colombier i -= 2;
5029a747e4fSDavid du Colombier if(i >= a->map->nel)
5039a747e4fSDavid du Colombier return -1;
5049a747e4fSDavid du Colombier fillstat(d, mkqid(D1st, a->map->el[i].n, 0, 0), a->map->t, 0);
5059a747e4fSDavid du Colombier return 0;
5069a747e4fSDavid du Colombier }
5079a747e4fSDavid du Colombier }
5089a747e4fSDavid du Colombier
5099a747e4fSDavid du Colombier static int
firstgen(int i,Dir * d,void * aux)5109a747e4fSDavid du Colombier firstgen(int i, Dir *d, void *aux)
5119a747e4fSDavid du Colombier {
5129a747e4fSDavid du Colombier ulong t;
5139a747e4fSDavid du Colombier Bogus *b;
5149a747e4fSDavid du Colombier int num;
5159a747e4fSDavid du Colombier Aux *a;
5169a747e4fSDavid du Colombier
5179a747e4fSDavid du Colombier b = aux;
5189a747e4fSDavid du Colombier num = qidnum(b->path);
5199a747e4fSDavid du Colombier a = b->a;
5209a747e4fSDavid du Colombier t = a->w->doc[a->n].time;
5219a747e4fSDavid du Colombier
5229a747e4fSDavid du Colombier if(i < Nfile){ /* file in first-level directory */
5239a747e4fSDavid du Colombier fillstat(d, mkqid(F1st, num, 0, i), t, 0);
5249a747e4fSDavid du Colombier return 0;
5259a747e4fSDavid du Colombier }
5269a747e4fSDavid du Colombier i -= Nfile;
5279a747e4fSDavid du Colombier
5289a747e4fSDavid du Colombier if(i < a->w->ndoc){ /* second-level (history) directory */
5299a747e4fSDavid du Colombier fillstat(d, mkqid(D2nd, num, i, 0), a->w->doc[i].time, 0);
5309a747e4fSDavid du Colombier return 0;
5319a747e4fSDavid du Colombier }
5329a747e4fSDavid du Colombier //i -= a->w->ndoc;
5339a747e4fSDavid du Colombier
5349a747e4fSDavid du Colombier return -1;
5359a747e4fSDavid du Colombier }
5369a747e4fSDavid du Colombier
5379a747e4fSDavid du Colombier static int
secondgen(int i,Dir * d,void * aux)5389a747e4fSDavid du Colombier secondgen(int i, Dir *d, void *aux)
5399a747e4fSDavid du Colombier {
5409a747e4fSDavid du Colombier Bogus *b;
5419a747e4fSDavid du Colombier uvlong path;
5429a747e4fSDavid du Colombier Aux *a;
5439a747e4fSDavid du Colombier
5449a747e4fSDavid du Colombier b = aux;
5459a747e4fSDavid du Colombier path = b->path;
5469a747e4fSDavid du Colombier a = b->a;
5479a747e4fSDavid du Colombier
5489a747e4fSDavid du Colombier if(i <= Qraw){ /* index.html, index.txt, raw */
5499a747e4fSDavid du Colombier fillstat(d, mkqid(F2nd, qidnum(path), qidvers(path), i), a->w->doc[a->n].time, 0);
5509a747e4fSDavid du Colombier return 0;
5519a747e4fSDavid du Colombier }
5529a747e4fSDavid du Colombier //i -= Qraw;
5539a747e4fSDavid du Colombier
5549a747e4fSDavid du Colombier return -1;
5559a747e4fSDavid du Colombier }
5569a747e4fSDavid du Colombier
5579a747e4fSDavid du Colombier static void
fsread(Req * r)5589a747e4fSDavid du Colombier fsread(Req *r)
5599a747e4fSDavid du Colombier {
5609a747e4fSDavid du Colombier char *t, *s;
5619a747e4fSDavid du Colombier uvlong path;
5629a747e4fSDavid du Colombier Aux *a;
5639a747e4fSDavid du Colombier Bogus b;
5649a747e4fSDavid du Colombier
5659a747e4fSDavid du Colombier a = r->fid->aux;
5669a747e4fSDavid du Colombier path = r->fid->qid.path;
5679a747e4fSDavid du Colombier b.a = a;
5689a747e4fSDavid du Colombier b.path = path;
5699a747e4fSDavid du Colombier switch(qidtype(path)){
5709a747e4fSDavid du Colombier default:
5719a747e4fSDavid du Colombier respond(r, "cannot happen (bad qid)");
5729a747e4fSDavid du Colombier return;
5739a747e4fSDavid du Colombier
5749a747e4fSDavid du Colombier case Droot:
5759a747e4fSDavid du Colombier if(a == nil || a->map == nil){
5769a747e4fSDavid du Colombier respond(r, "cannot happen (no map)");
5779a747e4fSDavid du Colombier return;
5789a747e4fSDavid du Colombier }
5799a747e4fSDavid du Colombier dirread9p(r, rootgen, &b);
5809a747e4fSDavid du Colombier respond(r, nil);
5819a747e4fSDavid du Colombier return;
5829a747e4fSDavid du Colombier
5839a747e4fSDavid du Colombier case D1st:
5849a747e4fSDavid du Colombier if(a == nil || a->w == nil){
5859a747e4fSDavid du Colombier respond(r, "cannot happen (no wh)");
5869a747e4fSDavid du Colombier return;
5879a747e4fSDavid du Colombier }
5889a747e4fSDavid du Colombier dirread9p(r, firstgen, &b);
5899a747e4fSDavid du Colombier respond(r, nil);
5909a747e4fSDavid du Colombier return;
5919a747e4fSDavid du Colombier
5929a747e4fSDavid du Colombier case D2nd:
5939a747e4fSDavid du Colombier dirread9p(r, secondgen, &b);
5949a747e4fSDavid du Colombier respond(r, nil);
5959a747e4fSDavid du Colombier return;
5969a747e4fSDavid du Colombier
5979a747e4fSDavid du Colombier case Fnew:
5989a747e4fSDavid du Colombier if(a->s){
5999a747e4fSDavid du Colombier respond(r, "protocol botch");
6009a747e4fSDavid du Colombier return;
6019a747e4fSDavid du Colombier }
6029a747e4fSDavid du Colombier /* fall through */
6039a747e4fSDavid du Colombier case Fmap:
6049a747e4fSDavid du Colombier t = numtoname(a->n);
6059a747e4fSDavid du Colombier if(t == nil){
6069a747e4fSDavid du Colombier respond(r, "unknown name");
6079a747e4fSDavid du Colombier return;
6089a747e4fSDavid du Colombier }
6099a747e4fSDavid du Colombier for(s=t; *s; s++)
6109a747e4fSDavid du Colombier if(*s == ' ')
6119a747e4fSDavid du Colombier *s = '_';
6129a747e4fSDavid du Colombier readstr(r, t);
6139a747e4fSDavid du Colombier free(t);
6149a747e4fSDavid du Colombier respond(r, nil);
6159a747e4fSDavid du Colombier return;
6169a747e4fSDavid du Colombier
6179a747e4fSDavid du Colombier case F1st:
6189a747e4fSDavid du Colombier case F2nd:
6199a747e4fSDavid du Colombier if(a == nil || a->s == nil){
6209a747e4fSDavid du Colombier respond(r, "cannot happen (no s)");
6219a747e4fSDavid du Colombier return;
6229a747e4fSDavid du Colombier }
6239a747e4fSDavid du Colombier readbuf(r, s_to_c(a->s), s_len(a->s));
6249a747e4fSDavid du Colombier respond(r, nil);
6259a747e4fSDavid du Colombier return;
6269a747e4fSDavid du Colombier }
6279a747e4fSDavid du Colombier }
6289a747e4fSDavid du Colombier
6299a747e4fSDavid du Colombier typedef struct Sread Sread;
6309a747e4fSDavid du Colombier struct Sread {
6319a747e4fSDavid du Colombier char *rp;
6329a747e4fSDavid du Colombier };
6339a747e4fSDavid du Colombier
6349a747e4fSDavid du Colombier static char*
Srdline(void * v,int c)6359a747e4fSDavid du Colombier Srdline(void *v, int c)
6369a747e4fSDavid du Colombier {
6379a747e4fSDavid du Colombier char *p, *rv;
6389a747e4fSDavid du Colombier Sread *s;
6399a747e4fSDavid du Colombier
6409a747e4fSDavid du Colombier s = v;
6419a747e4fSDavid du Colombier if(s->rp == nil)
6429a747e4fSDavid du Colombier rv = nil;
6439a747e4fSDavid du Colombier else if(p = strchr(s->rp, c)){
6449a747e4fSDavid du Colombier *p = '\0';
6459a747e4fSDavid du Colombier rv = s->rp;
6469a747e4fSDavid du Colombier s->rp = p+1;
6479a747e4fSDavid du Colombier }else{
6489a747e4fSDavid du Colombier rv = s->rp;
6499a747e4fSDavid du Colombier s->rp = nil;
6509a747e4fSDavid du Colombier }
6519a747e4fSDavid du Colombier return rv;
6529a747e4fSDavid du Colombier }
6539a747e4fSDavid du Colombier
6549a747e4fSDavid du Colombier static void
responderrstr(Req * r)6559a747e4fSDavid du Colombier responderrstr(Req *r)
6569a747e4fSDavid du Colombier {
6579a747e4fSDavid du Colombier char buf[ERRMAX];
6589a747e4fSDavid du Colombier
6599a747e4fSDavid du Colombier rerrstr(buf, sizeof buf);
6609a747e4fSDavid du Colombier if(buf[0] == '\0')
6619a747e4fSDavid du Colombier strcpy(buf, "unknown error");
6629a747e4fSDavid du Colombier respond(r, buf);
6639a747e4fSDavid du Colombier }
6649a747e4fSDavid du Colombier
6659a747e4fSDavid du Colombier static void
fswrite(Req * r)6669a747e4fSDavid du Colombier fswrite(Req *r)
6679a747e4fSDavid du Colombier {
6689a747e4fSDavid du Colombier char *author, *comment, *net, *err, *p, *title, tmp[40];
6699a747e4fSDavid du Colombier int rv, n;
6709a747e4fSDavid du Colombier ulong t;
6719a747e4fSDavid du Colombier Aux *a;
6729a747e4fSDavid du Colombier Fid *fid;
6739a747e4fSDavid du Colombier Sread s;
6749a747e4fSDavid du Colombier String *stmp;
6759a747e4fSDavid du Colombier Whist *w;
6769a747e4fSDavid du Colombier
6779a747e4fSDavid du Colombier fid = r->fid;
6789a747e4fSDavid du Colombier a = fid->aux;
6799a747e4fSDavid du Colombier switch(qidtype(fid->qid.path)){
6809a747e4fSDavid du Colombier case Fmap:
6819a747e4fSDavid du Colombier stmp = s_nappend(s_reset(nil), r->ifcall.data, r->ifcall.count);
6829a747e4fSDavid du Colombier a->n = nametonum(s_to_c(stmp));
6839a747e4fSDavid du Colombier s_free(stmp);
6849a747e4fSDavid du Colombier if(a->n < 0)
6859a747e4fSDavid du Colombier respond(r, "name not found");
6869a747e4fSDavid du Colombier else
6879a747e4fSDavid du Colombier respond(r, nil);
6889a747e4fSDavid du Colombier return;
6899a747e4fSDavid du Colombier case Fnew:
6909a747e4fSDavid du Colombier break;
6919a747e4fSDavid du Colombier default:
6929a747e4fSDavid du Colombier respond(r, "cannot happen");
6939a747e4fSDavid du Colombier return;
6949a747e4fSDavid du Colombier }
6959a747e4fSDavid du Colombier
6969a747e4fSDavid du Colombier if(a->s == nil){
6979a747e4fSDavid du Colombier respond(r, "protocol botch");
6989a747e4fSDavid du Colombier return;
6999a747e4fSDavid du Colombier }
7009a747e4fSDavid du Colombier if(r->ifcall.count==0){ /* do final processing */
7019a747e4fSDavid du Colombier s.rp = s_to_c(a->s);
7029a747e4fSDavid du Colombier w = nil;
7039a747e4fSDavid du Colombier err = "bad format";
7049a747e4fSDavid du Colombier if((title = Srdline(&s, '\n')) == nil){
7059a747e4fSDavid du Colombier Error:
7069a747e4fSDavid du Colombier if(w)
7079a747e4fSDavid du Colombier closewhist(w);
7089a747e4fSDavid du Colombier s_free(a->s);
7099a747e4fSDavid du Colombier a->s = nil;
7109a747e4fSDavid du Colombier respond(r, err);
7119a747e4fSDavid du Colombier return;
7129a747e4fSDavid du Colombier }
7139a747e4fSDavid du Colombier
7149a747e4fSDavid du Colombier w = emalloc(sizeof(*w));
7159a747e4fSDavid du Colombier incref(w);
7169a747e4fSDavid du Colombier w->title = estrdup(title);
7179a747e4fSDavid du Colombier
7189a747e4fSDavid du Colombier t = 0;
719af2e6ba6SDavid du Colombier author = estrdup(s_to_c(a->name));
7209a747e4fSDavid du Colombier
7219a747e4fSDavid du Colombier comment = nil;
7229a747e4fSDavid du Colombier while(s.rp && *s.rp && *s.rp != '\n'){
7239a747e4fSDavid du Colombier p = Srdline(&s, '\n');
7249a747e4fSDavid du Colombier assert(p != nil);
7259a747e4fSDavid du Colombier switch(p[0]){
7269a747e4fSDavid du Colombier case 'A':
7279a747e4fSDavid du Colombier free(author);
7289a747e4fSDavid du Colombier author = estrdup(p+1);
7299a747e4fSDavid du Colombier break;
7309a747e4fSDavid du Colombier case 'D':
7319a747e4fSDavid du Colombier t = strtoul(p+1, &p, 10);
7329a747e4fSDavid du Colombier if(*p != '\0')
7339a747e4fSDavid du Colombier goto Error;
7349a747e4fSDavid du Colombier break;
7359a747e4fSDavid du Colombier case 'C':
7369a747e4fSDavid du Colombier free(comment);
7379a747e4fSDavid du Colombier comment = estrdup(p+1);
7389a747e4fSDavid du Colombier break;
7399a747e4fSDavid du Colombier }
7409a747e4fSDavid du Colombier }
7419a747e4fSDavid du Colombier
7429a747e4fSDavid du Colombier w->doc = emalloc(sizeof(w->doc[0]));
7439a747e4fSDavid du Colombier w->doc->time = time(0);
7449a747e4fSDavid du Colombier w->doc->comment = comment;
7459a747e4fSDavid du Colombier
7469a747e4fSDavid du Colombier if(net = r->pool->srv->aux){
7479a747e4fSDavid du Colombier p = emalloc(strlen(author)+10+strlen(net));
7489a747e4fSDavid du Colombier strcpy(p, author);
7499a747e4fSDavid du Colombier strcat(p, " (");
7509a747e4fSDavid du Colombier strcat(p, net);
7519a747e4fSDavid du Colombier strcat(p, ")");
7529a747e4fSDavid du Colombier free(author);
7539a747e4fSDavid du Colombier author = p;
7549a747e4fSDavid du Colombier }
7559a747e4fSDavid du Colombier w->doc->author = author;
7569a747e4fSDavid du Colombier
7579a747e4fSDavid du Colombier if((w->doc->wtxt = Brdpage(Srdline, &s)) == nil){
7589a747e4fSDavid du Colombier err = "empty document";
7599a747e4fSDavid du Colombier goto Error;
7609a747e4fSDavid du Colombier }
7619a747e4fSDavid du Colombier
7629a747e4fSDavid du Colombier w->ndoc = 1;
7639a747e4fSDavid du Colombier if((n = allocnum(w->title, 0)) < 0)
7649a747e4fSDavid du Colombier goto Error;
7659a747e4fSDavid du Colombier sprint(tmp, "D%lud\n", w->doc->time);
7669a747e4fSDavid du Colombier a->s = s_reset(a->s);
7679a747e4fSDavid du Colombier a->s = doctext(a->s, w->doc);
7689a747e4fSDavid du Colombier rv = writepage(n, t, a->s, w->title);
7699a747e4fSDavid du Colombier s_free(a->s);
7709a747e4fSDavid du Colombier a->s = nil;
7719a747e4fSDavid du Colombier a->n = n;
7729a747e4fSDavid du Colombier closewhist(w);
7739a747e4fSDavid du Colombier if(rv < 0)
7749a747e4fSDavid du Colombier responderrstr(r);
7759a747e4fSDavid du Colombier else
7769a747e4fSDavid du Colombier respond(r, nil);
7779a747e4fSDavid du Colombier return;
7789a747e4fSDavid du Colombier }
7799a747e4fSDavid du Colombier
7809a747e4fSDavid du Colombier if(s_len(a->s)+r->ifcall.count > Maxfile){
7819a747e4fSDavid du Colombier respond(r, "file too large");
7829a747e4fSDavid du Colombier s_free(a->s);
7839a747e4fSDavid du Colombier a->s = nil;
7849a747e4fSDavid du Colombier return;
7859a747e4fSDavid du Colombier }
7869a747e4fSDavid du Colombier a->s = s_nappend(a->s, r->ifcall.data, r->ifcall.count);
7879a747e4fSDavid du Colombier r->ofcall.count = r->ifcall.count;
7889a747e4fSDavid du Colombier respond(r, nil);
7899a747e4fSDavid du Colombier }
7909a747e4fSDavid du Colombier
7919a747e4fSDavid du Colombier Srv wikisrv = {
7929a747e4fSDavid du Colombier .attach= fsattach,
7939a747e4fSDavid du Colombier .destroyfid= fsdestroyfid,
7949a747e4fSDavid du Colombier .clone= fsclone,
7959a747e4fSDavid du Colombier .walk1= fswalk1,
7969a747e4fSDavid du Colombier .open= fsopen,
7979a747e4fSDavid du Colombier .read= fsread,
7989a747e4fSDavid du Colombier .write= fswrite,
7999a747e4fSDavid du Colombier .stat= fsstat,
8009a747e4fSDavid du Colombier };
8019a747e4fSDavid du Colombier
8029a747e4fSDavid du Colombier void
usage(void)8039a747e4fSDavid du Colombier usage(void)
8049a747e4fSDavid du Colombier {
8059a747e4fSDavid du Colombier fprint(2, "usage: wikifs [-D] [-a addr]... [-m mtpt] [-p perm] [-s service] dir\n");
8069a747e4fSDavid du Colombier exits("usage");
8079a747e4fSDavid du Colombier }
8089a747e4fSDavid du Colombier
8099a747e4fSDavid du Colombier void
main(int argc,char ** argv)8109a747e4fSDavid du Colombier main(int argc, char **argv)
8119a747e4fSDavid du Colombier {
8129a747e4fSDavid du Colombier char **addr;
8139a747e4fSDavid du Colombier int i, naddr;
8149a747e4fSDavid du Colombier char *buf;
8159a747e4fSDavid du Colombier char *service, *mtpt;
8169a747e4fSDavid du Colombier ulong perm;
8179a747e4fSDavid du Colombier Dir d, *dp;
8189a747e4fSDavid du Colombier Srv *s;
8199a747e4fSDavid du Colombier
8209a747e4fSDavid du Colombier naddr = 0;
8219a747e4fSDavid du Colombier addr = nil;
8229a747e4fSDavid du Colombier perm = 0;
8239a747e4fSDavid du Colombier service = nil;
8249a747e4fSDavid du Colombier mtpt = "/mnt/wiki";
8259a747e4fSDavid du Colombier ARGBEGIN{
8269a747e4fSDavid du Colombier case 'D':
8279a747e4fSDavid du Colombier chatty9p++;
8289a747e4fSDavid du Colombier break;
8299a747e4fSDavid du Colombier case 'a':
8309a747e4fSDavid du Colombier if(naddr%8 == 0)
8319a747e4fSDavid du Colombier addr = erealloc(addr, (naddr+8)*sizeof(addr[0]));
8329a747e4fSDavid du Colombier addr[naddr++] = EARGF(usage());
8339a747e4fSDavid du Colombier break;
8349a747e4fSDavid du Colombier case 'm':
8359a747e4fSDavid du Colombier mtpt = EARGF(usage());
8369a747e4fSDavid du Colombier break;
8379a747e4fSDavid du Colombier case 'M':
8389a747e4fSDavid du Colombier mtpt = nil;
8399a747e4fSDavid du Colombier break;
8409a747e4fSDavid du Colombier case 'p':
8419a747e4fSDavid du Colombier perm = strtoul(EARGF(usage()), nil, 8);
8429a747e4fSDavid du Colombier break;
8439a747e4fSDavid du Colombier case 's':
8449a747e4fSDavid du Colombier service = EARGF(usage());
8459a747e4fSDavid du Colombier break;
8469a747e4fSDavid du Colombier default:
8479a747e4fSDavid du Colombier usage();
8489a747e4fSDavid du Colombier break;
8499a747e4fSDavid du Colombier }ARGEND
8509a747e4fSDavid du Colombier
8519a747e4fSDavid du Colombier if(argc != 1)
8529a747e4fSDavid du Colombier usage();
8539a747e4fSDavid du Colombier
8549a747e4fSDavid du Colombier if((dp = dirstat(argv[0])) == nil)
8559a747e4fSDavid du Colombier sysfatal("dirstat %s: %r", argv[0]);
8569a747e4fSDavid du Colombier if((dp->mode&DMDIR) == 0)
8579a747e4fSDavid du Colombier sysfatal("%s: not a directory", argv[0]);
8589a747e4fSDavid du Colombier free(dp);
8599a747e4fSDavid du Colombier wikidir = argv[0];
8609a747e4fSDavid du Colombier
8619a747e4fSDavid du Colombier currentmap(0);
8629a747e4fSDavid du Colombier
8639a747e4fSDavid du Colombier for(i=0; i<naddr; i++)
8649a747e4fSDavid du Colombier listensrv(&wikisrv, addr[i]);
8659a747e4fSDavid du Colombier
8669a747e4fSDavid du Colombier s = emalloc(sizeof *s);
8679a747e4fSDavid du Colombier *s = wikisrv;
8689a747e4fSDavid du Colombier postmountsrv(s, service, mtpt, MREPL|MCREATE);
8699a747e4fSDavid du Colombier if(perm){
8709a747e4fSDavid du Colombier buf = emalloc9p(5+strlen(service)+1);
8719a747e4fSDavid du Colombier strcpy(buf, "/srv/");
8729a747e4fSDavid du Colombier strcat(buf, service);
8739a747e4fSDavid du Colombier nulldir(&d);
8749a747e4fSDavid du Colombier d.mode = perm;
8759a747e4fSDavid du Colombier if(dirwstat(buf, &d) < 0)
8769a747e4fSDavid du Colombier fprint(2, "wstat: %r\n");
877*1052a86aSDavid du Colombier free(buf);
8789a747e4fSDavid du Colombier }
8799a747e4fSDavid du Colombier exits(nil);
8809a747e4fSDavid du Colombier }
881