1*7dd7cddfSDavid du Colombier #include <u.h> 2*7dd7cddfSDavid du Colombier #include <libc.h> 3*7dd7cddfSDavid du Colombier #include <draw.h> 4*7dd7cddfSDavid du Colombier #include <thread.h> 5*7dd7cddfSDavid du Colombier #include <cursor.h> 6*7dd7cddfSDavid du Colombier #include <mouse.h> 7*7dd7cddfSDavid du Colombier #include <keyboard.h> 8*7dd7cddfSDavid du Colombier #include <frame.h> 9*7dd7cddfSDavid du Colombier #include <auth.h> 10*7dd7cddfSDavid du Colombier #include <fcall.h> 11*7dd7cddfSDavid du Colombier #include "dat.h" 12*7dd7cddfSDavid du Colombier #include "fns.h" 13*7dd7cddfSDavid du Colombier 14*7dd7cddfSDavid du Colombier char Eperm[] = "permission denied"; 15*7dd7cddfSDavid du Colombier char Eexist[] = "file does not exist"; 16*7dd7cddfSDavid du Colombier char Enotdir[] = "not a directory"; 17*7dd7cddfSDavid du Colombier char Ebadfcall[] = "bad fcall type"; 18*7dd7cddfSDavid du Colombier char Eoffset[] = "illegal offset"; 19*7dd7cddfSDavid du Colombier 20*7dd7cddfSDavid du Colombier Dirtab dirtab[]= 21*7dd7cddfSDavid du Colombier { 22*7dd7cddfSDavid du Colombier { ".", Qdir|CHDIR, 0500|CHDIR }, 23*7dd7cddfSDavid du Colombier { "cons", Qcons, 0600 }, 24*7dd7cddfSDavid du Colombier { "cursor", Qcursor, 0600 }, 25*7dd7cddfSDavid du Colombier { "consctl", Qconsctl, 0200 }, 26*7dd7cddfSDavid du Colombier { "winid", Qwinid, 0400 }, 27*7dd7cddfSDavid du Colombier { "winname", Qwinname, 0400 }, 28*7dd7cddfSDavid du Colombier { "label", Qlabel, 0600 }, 29*7dd7cddfSDavid du Colombier { "mouse", Qmouse, 0600 }, 30*7dd7cddfSDavid du Colombier { "screen", Qscreen, 0400 }, 31*7dd7cddfSDavid du Colombier { "snarf", Qsnarf, 0600 }, 32*7dd7cddfSDavid du Colombier { "text", Qtext, 0400 }, 33*7dd7cddfSDavid du Colombier { "wdir", Qwdir, 0600 }, 34*7dd7cddfSDavid du Colombier { "wctl", Qwctl, 0600 }, 35*7dd7cddfSDavid du Colombier { "window", Qwindow, 0400 }, 36*7dd7cddfSDavid du Colombier { "wsys", Qwsys|CHDIR, 0500|CHDIR }, 37*7dd7cddfSDavid du Colombier { nil, } 38*7dd7cddfSDavid du Colombier }; 39*7dd7cddfSDavid du Colombier 40*7dd7cddfSDavid du Colombier static uint getclock(void); 41*7dd7cddfSDavid du Colombier static void filsysproc(void*); 42*7dd7cddfSDavid du Colombier static Fid* newfid(Filsys*, int); 43*7dd7cddfSDavid du Colombier static void dostat(Filsys*, int, Dirtab*, char*, uint); 44*7dd7cddfSDavid du Colombier 45*7dd7cddfSDavid du Colombier int clockfd; 46*7dd7cddfSDavid du Colombier 47*7dd7cddfSDavid du Colombier char srvpipe[64]; 48*7dd7cddfSDavid du Colombier char srvwctl[64]; 49*7dd7cddfSDavid du Colombier 50*7dd7cddfSDavid du Colombier static Xfid* filsysflush(Filsys*, Xfid*, Fid*); 51*7dd7cddfSDavid du Colombier static Xfid* filsyssession(Filsys*, Xfid*, Fid*); 52*7dd7cddfSDavid du Colombier static Xfid* filsysnop(Filsys*, Xfid*, Fid*); 53*7dd7cddfSDavid du Colombier static Xfid* filsysattach(Filsys*, Xfid*, Fid*); 54*7dd7cddfSDavid du Colombier static Xfid* filsysclone(Filsys*, Xfid*, Fid*); 55*7dd7cddfSDavid du Colombier static Xfid* filsyswalk(Filsys*, Xfid*, Fid*); 56*7dd7cddfSDavid du Colombier static Xfid* filsysclwalk(Filsys*, Xfid*, Fid*); 57*7dd7cddfSDavid du Colombier static Xfid* filsysopen(Filsys*, Xfid*, Fid*); 58*7dd7cddfSDavid du Colombier static Xfid* filsyscreate(Filsys*, Xfid*, Fid*); 59*7dd7cddfSDavid du Colombier static Xfid* filsysread(Filsys*, Xfid*, Fid*); 60*7dd7cddfSDavid du Colombier static Xfid* filsyswrite(Filsys*, Xfid*, Fid*); 61*7dd7cddfSDavid du Colombier static Xfid* filsysclunk(Filsys*, Xfid*, Fid*); 62*7dd7cddfSDavid du Colombier static Xfid* filsysremove(Filsys*, Xfid*, Fid*); 63*7dd7cddfSDavid du Colombier static Xfid* filsysstat(Filsys*, Xfid*, Fid*); 64*7dd7cddfSDavid du Colombier static Xfid* filsyswstat(Filsys*, Xfid*, Fid*); 65*7dd7cddfSDavid du Colombier 66*7dd7cddfSDavid du Colombier Xfid* (*fcall[Tmax])(Filsys*, Xfid*, Fid*) = 67*7dd7cddfSDavid du Colombier { 68*7dd7cddfSDavid du Colombier [Tflush] = filsysflush, 69*7dd7cddfSDavid du Colombier [Tsession] = filsyssession, 70*7dd7cddfSDavid du Colombier [Tnop] = filsysnop, 71*7dd7cddfSDavid du Colombier [Tattach] = filsysattach, 72*7dd7cddfSDavid du Colombier [Tclone] = filsysclone, 73*7dd7cddfSDavid du Colombier [Twalk] = filsyswalk, 74*7dd7cddfSDavid du Colombier [Tclwalk] = filsysclwalk, 75*7dd7cddfSDavid du Colombier [Topen] = filsysopen, 76*7dd7cddfSDavid du Colombier [Tcreate] = filsyscreate, 77*7dd7cddfSDavid du Colombier [Tread] = filsysread, 78*7dd7cddfSDavid du Colombier [Twrite] = filsyswrite, 79*7dd7cddfSDavid du Colombier [Tclunk] = filsysclunk, 80*7dd7cddfSDavid du Colombier [Tremove]= filsysremove, 81*7dd7cddfSDavid du Colombier [Tstat] = filsysstat, 82*7dd7cddfSDavid du Colombier [Twstat] = filsyswstat, 83*7dd7cddfSDavid du Colombier }; 84*7dd7cddfSDavid du Colombier 85*7dd7cddfSDavid du Colombier void 86*7dd7cddfSDavid du Colombier post(char *name, char *envname, int srvfd) 87*7dd7cddfSDavid du Colombier { 88*7dd7cddfSDavid du Colombier int fd; 89*7dd7cddfSDavid du Colombier char buf[32]; 90*7dd7cddfSDavid du Colombier 91*7dd7cddfSDavid du Colombier fd = create(name, OWRITE, 0600); 92*7dd7cddfSDavid du Colombier if(fd < 0) 93*7dd7cddfSDavid du Colombier error(name); 94*7dd7cddfSDavid du Colombier sprint(buf, "%d",srvfd); 95*7dd7cddfSDavid du Colombier if(write(fd, buf, strlen(buf)) != strlen(buf)) 96*7dd7cddfSDavid du Colombier error("srv write"); 97*7dd7cddfSDavid du Colombier close(fd); 98*7dd7cddfSDavid du Colombier putenv(envname, name); 99*7dd7cddfSDavid du Colombier } 100*7dd7cddfSDavid du Colombier 101*7dd7cddfSDavid du Colombier /* 102*7dd7cddfSDavid du Colombier * Build pipe with OCEXEC set on second fd. 103*7dd7cddfSDavid du Colombier * Can't put it on both because we want to post one in /srv. 104*7dd7cddfSDavid du Colombier */ 105*7dd7cddfSDavid du Colombier int 106*7dd7cddfSDavid du Colombier cexecpipe(int *p0, int *p1) 107*7dd7cddfSDavid du Colombier { 108*7dd7cddfSDavid du Colombier /* pipe the hard way to get close on exec */ 109*7dd7cddfSDavid du Colombier if(bind("#|", "/mnt", MREPL) < 0) 110*7dd7cddfSDavid du Colombier return -1; 111*7dd7cddfSDavid du Colombier *p0 = open("/mnt/data", ORDWR); 112*7dd7cddfSDavid du Colombier *p1 = open("/mnt/data1", ORDWR|OCEXEC); 113*7dd7cddfSDavid du Colombier unmount(nil, "/mnt"); 114*7dd7cddfSDavid du Colombier if(*p0<0 || *p1<0) 115*7dd7cddfSDavid du Colombier return -1; 116*7dd7cddfSDavid du Colombier return 0; 117*7dd7cddfSDavid du Colombier } 118*7dd7cddfSDavid du Colombier 119*7dd7cddfSDavid du Colombier Filsys* 120*7dd7cddfSDavid du Colombier filsysinit(Channel *cxfidalloc) 121*7dd7cddfSDavid du Colombier { 122*7dd7cddfSDavid du Colombier int n, fd, pid, p0; 123*7dd7cddfSDavid du Colombier Filsys *fs; 124*7dd7cddfSDavid du Colombier Channel *c; 125*7dd7cddfSDavid du Colombier 126*7dd7cddfSDavid du Colombier fs = emalloc(sizeof(Filsys)); 127*7dd7cddfSDavid du Colombier if(cexecpipe(&fs->cfd, &fs->sfd) < 0) 128*7dd7cddfSDavid du Colombier goto Rescue; 129*7dd7cddfSDavid du Colombier fmtinstall('F', fcallconv); 130*7dd7cddfSDavid du Colombier clockfd = open("/dev/time", OREAD|OCEXEC); 131*7dd7cddfSDavid du Colombier fd = open("/dev/user", OREAD); 132*7dd7cddfSDavid du Colombier strncpy(fs->user, "Jean-Paul_Belmondo", NAMELEN); 133*7dd7cddfSDavid du Colombier if(fd >= 0){ 134*7dd7cddfSDavid du Colombier n = read(fd, fs->user, NAMELEN); 135*7dd7cddfSDavid du Colombier if(n > 0) 136*7dd7cddfSDavid du Colombier fs->user[n] = 0; 137*7dd7cddfSDavid du Colombier close(fd); 138*7dd7cddfSDavid du Colombier } 139*7dd7cddfSDavid du Colombier fs->cxfidalloc = cxfidalloc; 140*7dd7cddfSDavid du Colombier pid = getpid(); 141*7dd7cddfSDavid du Colombier 142*7dd7cddfSDavid du Colombier /* 143*7dd7cddfSDavid du Colombier * Create and post wctl pipe 144*7dd7cddfSDavid du Colombier */ 145*7dd7cddfSDavid du Colombier if(cexecpipe(&p0, &wctlfd) < 0) 146*7dd7cddfSDavid du Colombier goto Rescue; 147*7dd7cddfSDavid du Colombier sprint(srvwctl, "/srv/riowctl.%s.%d", fs->user, pid); 148*7dd7cddfSDavid du Colombier post(srvwctl, "wctl", p0); 149*7dd7cddfSDavid du Colombier close(p0); 150*7dd7cddfSDavid du Colombier 151*7dd7cddfSDavid du Colombier /* 152*7dd7cddfSDavid du Colombier * Post srv pipe 153*7dd7cddfSDavid du Colombier */ 154*7dd7cddfSDavid du Colombier sprint(srvpipe, "/srv/rio.%s.%d", fs->user, pid); 155*7dd7cddfSDavid du Colombier post(srvpipe, "wsys", fs->cfd); 156*7dd7cddfSDavid du Colombier 157*7dd7cddfSDavid du Colombier /* 158*7dd7cddfSDavid du Colombier * Start server processes 159*7dd7cddfSDavid du Colombier */ 160*7dd7cddfSDavid du Colombier c = chancreate(sizeof(char*), 0); 161*7dd7cddfSDavid du Colombier if(c == nil) 162*7dd7cddfSDavid du Colombier error("wctl channel"); 163*7dd7cddfSDavid du Colombier proccreate(wctlproc, c, 4096); 164*7dd7cddfSDavid du Colombier threadcreate(wctlthread, c, 4096); 165*7dd7cddfSDavid du Colombier proccreate(filsysproc, fs, 10000); 166*7dd7cddfSDavid du Colombier 167*7dd7cddfSDavid du Colombier return fs; 168*7dd7cddfSDavid du Colombier 169*7dd7cddfSDavid du Colombier Rescue: 170*7dd7cddfSDavid du Colombier free(fs); 171*7dd7cddfSDavid du Colombier return nil; 172*7dd7cddfSDavid du Colombier } 173*7dd7cddfSDavid du Colombier 174*7dd7cddfSDavid du Colombier static 175*7dd7cddfSDavid du Colombier void 176*7dd7cddfSDavid du Colombier filsysproc(void *arg) 177*7dd7cddfSDavid du Colombier { 178*7dd7cddfSDavid du Colombier int n; 179*7dd7cddfSDavid du Colombier Xfid *x; 180*7dd7cddfSDavid du Colombier Fid *f; 181*7dd7cddfSDavid du Colombier Fcall t; 182*7dd7cddfSDavid du Colombier char *buf; 183*7dd7cddfSDavid du Colombier Filsys *fs; 184*7dd7cddfSDavid du Colombier 185*7dd7cddfSDavid du Colombier fs = arg; 186*7dd7cddfSDavid du Colombier fs->pid = getpid(); 187*7dd7cddfSDavid du Colombier x = nil; 188*7dd7cddfSDavid du Colombier for(;;){ 189*7dd7cddfSDavid du Colombier buf = malloc(MAXFDATA+MAXMSG); 190*7dd7cddfSDavid du Colombier n = read(fs->sfd, buf, MAXFDATA+MAXMSG); 191*7dd7cddfSDavid du Colombier if(n < 0) 192*7dd7cddfSDavid du Colombier error("i/o error on server channel"); 193*7dd7cddfSDavid du Colombier if(n == 0) 194*7dd7cddfSDavid du Colombier error("eof on server channel"); 195*7dd7cddfSDavid du Colombier if(x == nil){ 196*7dd7cddfSDavid du Colombier send(fs->cxfidalloc, nil); 197*7dd7cddfSDavid du Colombier recv(fs->cxfidalloc, &x); 198*7dd7cddfSDavid du Colombier x->fs = fs; 199*7dd7cddfSDavid du Colombier } 200*7dd7cddfSDavid du Colombier x->buf = buf; 201*7dd7cddfSDavid du Colombier if(convM2S(buf, x, n) != n) 202*7dd7cddfSDavid du Colombier error("convert error in convM2S"); 203*7dd7cddfSDavid du Colombier if(fcall[x->type] == nil) 204*7dd7cddfSDavid du Colombier x = filsysrespond(fs, x, &t, Ebadfcall); 205*7dd7cddfSDavid du Colombier else{ 206*7dd7cddfSDavid du Colombier if(x->type==Tnop || x->type==Tsession) 207*7dd7cddfSDavid du Colombier f = nil; 208*7dd7cddfSDavid du Colombier else 209*7dd7cddfSDavid du Colombier f = newfid(fs, x->fid); 210*7dd7cddfSDavid du Colombier x->f = f; 211*7dd7cddfSDavid du Colombier x = (*fcall[x->type])(fs, x, f); 212*7dd7cddfSDavid du Colombier } 213*7dd7cddfSDavid du Colombier } 214*7dd7cddfSDavid du Colombier } 215*7dd7cddfSDavid du Colombier 216*7dd7cddfSDavid du Colombier void 217*7dd7cddfSDavid du Colombier filsysclose(Filsys *fs) 218*7dd7cddfSDavid du Colombier { 219*7dd7cddfSDavid du Colombier if(fs == nil) 220*7dd7cddfSDavid du Colombier return; 221*7dd7cddfSDavid du Colombier close(fs->sfd); 222*7dd7cddfSDavid du Colombier fs->sfd = -1; 223*7dd7cddfSDavid du Colombier close(fs->cfd); 224*7dd7cddfSDavid du Colombier fs->cfd = -1; 225*7dd7cddfSDavid du Colombier remove(srvpipe); 226*7dd7cddfSDavid du Colombier remove(srvwctl); 227*7dd7cddfSDavid du Colombier } 228*7dd7cddfSDavid du Colombier 229*7dd7cddfSDavid du Colombier /* 230*7dd7cddfSDavid du Colombier * Called only from a different FD group 231*7dd7cddfSDavid du Colombier */ 232*7dd7cddfSDavid du Colombier int 233*7dd7cddfSDavid du Colombier filsysmount(Filsys *fs, int id) 234*7dd7cddfSDavid du Colombier { 235*7dd7cddfSDavid du Colombier char buf[3*NAMELEN+CHALLEN+DOMLEN+1]; 236*7dd7cddfSDavid du Colombier 237*7dd7cddfSDavid du Colombier close(fs->sfd); /* close server end so mount won't hang if exiting */ 238*7dd7cddfSDavid du Colombier if(fsession(fs->cfd, buf) < 0){ 239*7dd7cddfSDavid du Colombier threadprint(2, "fsession failed: %r\n"); 240*7dd7cddfSDavid du Colombier return -1; 241*7dd7cddfSDavid du Colombier } 242*7dd7cddfSDavid du Colombier sprint(buf, "%d", id); 243*7dd7cddfSDavid du Colombier if(mount(fs->cfd, "/mnt/wsys", MREPL, buf) < 0){ 244*7dd7cddfSDavid du Colombier threadprint(2, "mount failed: %r\n"); 245*7dd7cddfSDavid du Colombier return -1; 246*7dd7cddfSDavid du Colombier } 247*7dd7cddfSDavid du Colombier if(bind("/mnt/wsys", "/dev", MBEFORE) < 0){ 248*7dd7cddfSDavid du Colombier threadprint(2, "bind failed: %r\n"); 249*7dd7cddfSDavid du Colombier return -1; 250*7dd7cddfSDavid du Colombier } 251*7dd7cddfSDavid du Colombier return 0; 252*7dd7cddfSDavid du Colombier } 253*7dd7cddfSDavid du Colombier 254*7dd7cddfSDavid du Colombier Xfid* 255*7dd7cddfSDavid du Colombier filsysrespond(Filsys *fs, Xfid *x, Fcall *t, char *err) 256*7dd7cddfSDavid du Colombier { 257*7dd7cddfSDavid du Colombier int n; 258*7dd7cddfSDavid du Colombier 259*7dd7cddfSDavid du Colombier if(err){ 260*7dd7cddfSDavid du Colombier t->type = Rerror; 261*7dd7cddfSDavid du Colombier strncpy(t->ename, err, ERRLEN); 262*7dd7cddfSDavid du Colombier }else 263*7dd7cddfSDavid du Colombier t->type = x->type+1; 264*7dd7cddfSDavid du Colombier t->fid = x->fid; 265*7dd7cddfSDavid du Colombier t->tag = x->tag; 266*7dd7cddfSDavid du Colombier if(x->buf == nil) 267*7dd7cddfSDavid du Colombier x->buf = malloc(MAXFDATA+MAXMSG); 268*7dd7cddfSDavid du Colombier n = convS2M(t, x->buf); 269*7dd7cddfSDavid du Colombier if(n < 0) 270*7dd7cddfSDavid du Colombier error("convert error in convS2M"); 271*7dd7cddfSDavid du Colombier if(write(fs->sfd, x->buf, n) != n) 272*7dd7cddfSDavid du Colombier error("write error in respond"); 273*7dd7cddfSDavid du Colombier free(x->buf); 274*7dd7cddfSDavid du Colombier x->buf = nil; 275*7dd7cddfSDavid du Colombier return x; 276*7dd7cddfSDavid du Colombier } 277*7dd7cddfSDavid du Colombier 278*7dd7cddfSDavid du Colombier void 279*7dd7cddfSDavid du Colombier filsyscancel(Xfid *x) 280*7dd7cddfSDavid du Colombier { 281*7dd7cddfSDavid du Colombier if(x->buf){ 282*7dd7cddfSDavid du Colombier free(x->buf); 283*7dd7cddfSDavid du Colombier x->buf = nil; 284*7dd7cddfSDavid du Colombier } 285*7dd7cddfSDavid du Colombier } 286*7dd7cddfSDavid du Colombier 287*7dd7cddfSDavid du Colombier static 288*7dd7cddfSDavid du Colombier Xfid* 289*7dd7cddfSDavid du Colombier filsysnop(Filsys *fs, Xfid *x, Fid*) 290*7dd7cddfSDavid du Colombier { 291*7dd7cddfSDavid du Colombier Fcall t; 292*7dd7cddfSDavid du Colombier 293*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil); 294*7dd7cddfSDavid du Colombier } 295*7dd7cddfSDavid du Colombier 296*7dd7cddfSDavid du Colombier static 297*7dd7cddfSDavid du Colombier Xfid* 298*7dd7cddfSDavid du Colombier filsyssession(Filsys *fs, Xfid *x, Fid*) 299*7dd7cddfSDavid du Colombier { 300*7dd7cddfSDavid du Colombier Fcall t; 301*7dd7cddfSDavid du Colombier 302*7dd7cddfSDavid du Colombier memset(&t, 0, sizeof t); 303*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil); 304*7dd7cddfSDavid du Colombier } 305*7dd7cddfSDavid du Colombier 306*7dd7cddfSDavid du Colombier static 307*7dd7cddfSDavid du Colombier Xfid* 308*7dd7cddfSDavid du Colombier filsysflush(Filsys*, Xfid *x, Fid*) 309*7dd7cddfSDavid du Colombier { 310*7dd7cddfSDavid du Colombier sendp(x->c, xfidflush); 311*7dd7cddfSDavid du Colombier return nil; 312*7dd7cddfSDavid du Colombier } 313*7dd7cddfSDavid du Colombier 314*7dd7cddfSDavid du Colombier static 315*7dd7cddfSDavid du Colombier Xfid* 316*7dd7cddfSDavid du Colombier filsysattach(Filsys *, Xfid *x, Fid *f) 317*7dd7cddfSDavid du Colombier { 318*7dd7cddfSDavid du Colombier Fcall t; 319*7dd7cddfSDavid du Colombier 320*7dd7cddfSDavid du Colombier if(strcmp(x->uname, x->fs->user) != 0) 321*7dd7cddfSDavid du Colombier return filsysrespond(x->fs, x, &t, Eperm); 322*7dd7cddfSDavid du Colombier f->busy = TRUE; 323*7dd7cddfSDavid du Colombier f->open = FALSE; 324*7dd7cddfSDavid du Colombier f->qid = (Qid){CHDIR|Qdir, 0}; 325*7dd7cddfSDavid du Colombier f->dir = dirtab; 326*7dd7cddfSDavid du Colombier f->nrpart = 0; 327*7dd7cddfSDavid du Colombier sendp(x->c, xfidattach); 328*7dd7cddfSDavid du Colombier return nil; 329*7dd7cddfSDavid du Colombier } 330*7dd7cddfSDavid du Colombier 331*7dd7cddfSDavid du Colombier static 332*7dd7cddfSDavid du Colombier Xfid* 333*7dd7cddfSDavid du Colombier filsysclone(Filsys *fs, Xfid *x, Fid *f) 334*7dd7cddfSDavid du Colombier { 335*7dd7cddfSDavid du Colombier Fid *nf; 336*7dd7cddfSDavid du Colombier Fcall t; 337*7dd7cddfSDavid du Colombier 338*7dd7cddfSDavid du Colombier if(f->open) 339*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, "is open"); 340*7dd7cddfSDavid du Colombier /* BUG: check exists */ 341*7dd7cddfSDavid du Colombier nf = newfid(fs, x->newfid); 342*7dd7cddfSDavid du Colombier nf->busy = TRUE; 343*7dd7cddfSDavid du Colombier nf->open = FALSE; 344*7dd7cddfSDavid du Colombier nf->dir = f->dir; 345*7dd7cddfSDavid du Colombier nf->qid = f->qid; 346*7dd7cddfSDavid du Colombier nf->w = f->w; 347*7dd7cddfSDavid du Colombier incref(f->w); 348*7dd7cddfSDavid du Colombier nf->nrpart = 0; /* not open, so must be zero */ 349*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil); 350*7dd7cddfSDavid du Colombier } 351*7dd7cddfSDavid du Colombier 352*7dd7cddfSDavid du Colombier static 353*7dd7cddfSDavid du Colombier Xfid* 354*7dd7cddfSDavid du Colombier filsyswalk(Filsys *fs, Xfid *x, Fid *f) 355*7dd7cddfSDavid du Colombier { 356*7dd7cddfSDavid du Colombier Fcall t; 357*7dd7cddfSDavid du Colombier int c, i, id; 358*7dd7cddfSDavid du Colombier uint qid; 359*7dd7cddfSDavid du Colombier Dirtab *d; 360*7dd7cddfSDavid du Colombier Window *w; 361*7dd7cddfSDavid du Colombier 362*7dd7cddfSDavid du Colombier if((f->qid.path & CHDIR) == 0) 363*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Enotdir); 364*7dd7cddfSDavid du Colombier if(strcmp(x->name, "..") == 0){ 365*7dd7cddfSDavid du Colombier qid = Qdir|CHDIR; 366*7dd7cddfSDavid du Colombier if(FILE(f->qid) == Qwsysdir) 367*7dd7cddfSDavid du Colombier qid = Qwsys|CHDIR; 368*7dd7cddfSDavid du Colombier id = 0; 369*7dd7cddfSDavid du Colombier goto Found; 370*7dd7cddfSDavid du Colombier } 371*7dd7cddfSDavid du Colombier if(f->qid.path == (CHDIR|Qwsys)){ 372*7dd7cddfSDavid du Colombier /* is it a numeric name? */ 373*7dd7cddfSDavid du Colombier for(i=0; (c=x->name[i]); i++) 374*7dd7cddfSDavid du Colombier if(c<'0' || '9'<c) 375*7dd7cddfSDavid du Colombier goto Notfound; 376*7dd7cddfSDavid du Colombier /* yes: it's a directory */ 377*7dd7cddfSDavid du Colombier id = atoi(x->name); 378*7dd7cddfSDavid du Colombier qlock(&all); 379*7dd7cddfSDavid du Colombier w = wlookid(id); 380*7dd7cddfSDavid du Colombier if(w == nil){ 381*7dd7cddfSDavid du Colombier qunlock(&all); 382*7dd7cddfSDavid du Colombier goto Notfound; 383*7dd7cddfSDavid du Colombier } 384*7dd7cddfSDavid du Colombier qid = CHDIR|Qwsysdir; 385*7dd7cddfSDavid du Colombier qunlock(&all); 386*7dd7cddfSDavid du Colombier incref(w); 387*7dd7cddfSDavid du Colombier sendp(winclosechan, f->w); 388*7dd7cddfSDavid du Colombier f->w = w; 389*7dd7cddfSDavid du Colombier f->dir = dirtab; 390*7dd7cddfSDavid du Colombier goto Found; 391*7dd7cddfSDavid du Colombier } 392*7dd7cddfSDavid du Colombier 393*7dd7cddfSDavid du Colombier if(snarffd>=0 && strcmp(x->name, "snarf")==0) 394*7dd7cddfSDavid du Colombier goto Notfound; 395*7dd7cddfSDavid du Colombier id = WIN(f->qid); 396*7dd7cddfSDavid du Colombier d = dirtab; 397*7dd7cddfSDavid du Colombier d++; /* skip '.' */ 398*7dd7cddfSDavid du Colombier for(; d->name; d++) 399*7dd7cddfSDavid du Colombier if(strcmp(x->name, d->name) == 0){ 400*7dd7cddfSDavid du Colombier qid = d->qid; 401*7dd7cddfSDavid du Colombier f->dir = d; 402*7dd7cddfSDavid du Colombier goto Found; 403*7dd7cddfSDavid du Colombier } 404*7dd7cddfSDavid du Colombier 405*7dd7cddfSDavid du Colombier Notfound: 406*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eexist); 407*7dd7cddfSDavid du Colombier 408*7dd7cddfSDavid du Colombier Found: 409*7dd7cddfSDavid du Colombier f->qid = (Qid){QID(id, qid), 0}; 410*7dd7cddfSDavid du Colombier t.qid = f->qid; 411*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil); 412*7dd7cddfSDavid du Colombier } 413*7dd7cddfSDavid du Colombier 414*7dd7cddfSDavid du Colombier static 415*7dd7cddfSDavid du Colombier Xfid* 416*7dd7cddfSDavid du Colombier filsysclwalk(Filsys *fs, Xfid *x, Fid*) 417*7dd7cddfSDavid du Colombier { 418*7dd7cddfSDavid du Colombier Fcall t; 419*7dd7cddfSDavid du Colombier 420*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, "clwalk not implemented"); 421*7dd7cddfSDavid du Colombier } 422*7dd7cddfSDavid du Colombier 423*7dd7cddfSDavid du Colombier static 424*7dd7cddfSDavid du Colombier Xfid* 425*7dd7cddfSDavid du Colombier filsysopen(Filsys *fs, Xfid *x, Fid *f) 426*7dd7cddfSDavid du Colombier { 427*7dd7cddfSDavid du Colombier Fcall t; 428*7dd7cddfSDavid du Colombier int m; 429*7dd7cddfSDavid du Colombier 430*7dd7cddfSDavid du Colombier /* can't truncate anything, so just disregard */ 431*7dd7cddfSDavid du Colombier x->mode &= ~(OTRUNC|OCEXEC); 432*7dd7cddfSDavid du Colombier /* can't execute or remove anything */ 433*7dd7cddfSDavid du Colombier if(x->mode==OEXEC || (x->mode&ORCLOSE)) 434*7dd7cddfSDavid du Colombier goto Deny; 435*7dd7cddfSDavid du Colombier switch(x->mode){ 436*7dd7cddfSDavid du Colombier default: 437*7dd7cddfSDavid du Colombier goto Deny; 438*7dd7cddfSDavid du Colombier case OREAD: 439*7dd7cddfSDavid du Colombier m = 0400; 440*7dd7cddfSDavid du Colombier break; 441*7dd7cddfSDavid du Colombier case OWRITE: 442*7dd7cddfSDavid du Colombier m = 0200; 443*7dd7cddfSDavid du Colombier break; 444*7dd7cddfSDavid du Colombier case ORDWR: 445*7dd7cddfSDavid du Colombier m = 0600; 446*7dd7cddfSDavid du Colombier break; 447*7dd7cddfSDavid du Colombier } 448*7dd7cddfSDavid du Colombier if(((f->dir->perm&~(CHDIR|CHAPPEND))&m) != m) 449*7dd7cddfSDavid du Colombier goto Deny; 450*7dd7cddfSDavid du Colombier 451*7dd7cddfSDavid du Colombier sendp(x->c, xfidopen); 452*7dd7cddfSDavid du Colombier return nil; 453*7dd7cddfSDavid du Colombier 454*7dd7cddfSDavid du Colombier Deny: 455*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm); 456*7dd7cddfSDavid du Colombier } 457*7dd7cddfSDavid du Colombier 458*7dd7cddfSDavid du Colombier static 459*7dd7cddfSDavid du Colombier Xfid* 460*7dd7cddfSDavid du Colombier filsyscreate(Filsys *fs, Xfid *x, Fid*) 461*7dd7cddfSDavid du Colombier { 462*7dd7cddfSDavid du Colombier Fcall t; 463*7dd7cddfSDavid du Colombier 464*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm); 465*7dd7cddfSDavid du Colombier } 466*7dd7cddfSDavid du Colombier 467*7dd7cddfSDavid du Colombier static 468*7dd7cddfSDavid du Colombier int 469*7dd7cddfSDavid du Colombier idcmp(void *a, void *b) 470*7dd7cddfSDavid du Colombier { 471*7dd7cddfSDavid du Colombier return *(int*)a - *(int*)b; 472*7dd7cddfSDavid du Colombier } 473*7dd7cddfSDavid du Colombier 474*7dd7cddfSDavid du Colombier static 475*7dd7cddfSDavid du Colombier Xfid* 476*7dd7cddfSDavid du Colombier filsysread(Filsys *fs, Xfid *x, Fid *f) 477*7dd7cddfSDavid du Colombier { 478*7dd7cddfSDavid du Colombier Fcall t; 479*7dd7cddfSDavid du Colombier char *b; 480*7dd7cddfSDavid du Colombier int i, n, o, e, j, k, *ids; 481*7dd7cddfSDavid du Colombier Dirtab *d, dt; 482*7dd7cddfSDavid du Colombier uint clock; 483*7dd7cddfSDavid du Colombier char buf[16]; 484*7dd7cddfSDavid du Colombier 485*7dd7cddfSDavid du Colombier if((f->qid.path & CHDIR) == 0){ 486*7dd7cddfSDavid du Colombier sendp(x->c, xfidread); 487*7dd7cddfSDavid du Colombier return nil; 488*7dd7cddfSDavid du Colombier } 489*7dd7cddfSDavid du Colombier if(x->offset % DIRLEN) 490*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eoffset); 491*7dd7cddfSDavid du Colombier o = x->offset; 492*7dd7cddfSDavid du Colombier e = x->offset+x->count; 493*7dd7cddfSDavid du Colombier clock = getclock(); 494*7dd7cddfSDavid du Colombier b = malloc(MAXFDATA+MAXMSG); 495*7dd7cddfSDavid du Colombier n = 0; 496*7dd7cddfSDavid du Colombier switch(FILE(f->qid)){ 497*7dd7cddfSDavid du Colombier case Qdir: 498*7dd7cddfSDavid du Colombier case Qwsysdir: 499*7dd7cddfSDavid du Colombier d = dirtab; 500*7dd7cddfSDavid du Colombier d++; /* first entry is '.' */ 501*7dd7cddfSDavid du Colombier for(i=0; d->name!=nil && i+DIRLEN<e; i+=DIRLEN){ 502*7dd7cddfSDavid du Colombier if(i >= o){ 503*7dd7cddfSDavid du Colombier dostat(fs, WIN(x->f->qid), d, b+n, clock); 504*7dd7cddfSDavid du Colombier n += DIRLEN; 505*7dd7cddfSDavid du Colombier } 506*7dd7cddfSDavid du Colombier d++; 507*7dd7cddfSDavid du Colombier } 508*7dd7cddfSDavid du Colombier break; 509*7dd7cddfSDavid du Colombier case Qwsys: 510*7dd7cddfSDavid du Colombier qlock(&all); 511*7dd7cddfSDavid du Colombier ids = emalloc(nwindow*sizeof(int)); 512*7dd7cddfSDavid du Colombier for(j=0; j<nwindow; j++) 513*7dd7cddfSDavid du Colombier ids[j] = window[j]->id; 514*7dd7cddfSDavid du Colombier qunlock(&all); 515*7dd7cddfSDavid du Colombier qsort(ids, nwindow, sizeof ids[0], idcmp); 516*7dd7cddfSDavid du Colombier dt.name = buf; 517*7dd7cddfSDavid du Colombier for(i=0, j=0; j<nwindow && i+DIRLEN<e; i+=DIRLEN){ 518*7dd7cddfSDavid du Colombier if(i >= o){ 519*7dd7cddfSDavid du Colombier k = ids[j]; 520*7dd7cddfSDavid du Colombier sprint(dt.name, "%d", k); 521*7dd7cddfSDavid du Colombier dt.qid = QID(k, CHDIR); 522*7dd7cddfSDavid du Colombier dt.perm = CHDIR|0700; 523*7dd7cddfSDavid du Colombier dostat(fs, k, &dt, b+n, clock); 524*7dd7cddfSDavid du Colombier n += DIRLEN; 525*7dd7cddfSDavid du Colombier } 526*7dd7cddfSDavid du Colombier j++; 527*7dd7cddfSDavid du Colombier } 528*7dd7cddfSDavid du Colombier free(ids); 529*7dd7cddfSDavid du Colombier break; 530*7dd7cddfSDavid du Colombier } 531*7dd7cddfSDavid du Colombier t.data = b; 532*7dd7cddfSDavid du Colombier t.count = n; 533*7dd7cddfSDavid du Colombier filsysrespond(fs, x, &t, nil); 534*7dd7cddfSDavid du Colombier free(b); 535*7dd7cddfSDavid du Colombier return x; 536*7dd7cddfSDavid du Colombier } 537*7dd7cddfSDavid du Colombier 538*7dd7cddfSDavid du Colombier static 539*7dd7cddfSDavid du Colombier Xfid* 540*7dd7cddfSDavid du Colombier filsyswrite(Filsys*, Xfid *x, Fid*) 541*7dd7cddfSDavid du Colombier { 542*7dd7cddfSDavid du Colombier sendp(x->c, xfidwrite); 543*7dd7cddfSDavid du Colombier return nil; 544*7dd7cddfSDavid du Colombier } 545*7dd7cddfSDavid du Colombier 546*7dd7cddfSDavid du Colombier static 547*7dd7cddfSDavid du Colombier Xfid* 548*7dd7cddfSDavid du Colombier filsysclunk(Filsys *fs, Xfid *x, Fid *f) 549*7dd7cddfSDavid du Colombier { 550*7dd7cddfSDavid du Colombier Fcall t; 551*7dd7cddfSDavid du Colombier 552*7dd7cddfSDavid du Colombier if(f->open){ 553*7dd7cddfSDavid du Colombier f->busy = FALSE; 554*7dd7cddfSDavid du Colombier f->open = FALSE; 555*7dd7cddfSDavid du Colombier sendp(x->c, xfidclose); 556*7dd7cddfSDavid du Colombier return nil; 557*7dd7cddfSDavid du Colombier } 558*7dd7cddfSDavid du Colombier if(f->w) 559*7dd7cddfSDavid du Colombier sendp(winclosechan, f->w); 560*7dd7cddfSDavid du Colombier f->busy = FALSE; 561*7dd7cddfSDavid du Colombier f->open = FALSE; 562*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil); 563*7dd7cddfSDavid du Colombier } 564*7dd7cddfSDavid du Colombier 565*7dd7cddfSDavid du Colombier static 566*7dd7cddfSDavid du Colombier Xfid* 567*7dd7cddfSDavid du Colombier filsysremove(Filsys *fs, Xfid *x, Fid*) 568*7dd7cddfSDavid du Colombier { 569*7dd7cddfSDavid du Colombier Fcall t; 570*7dd7cddfSDavid du Colombier 571*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm); 572*7dd7cddfSDavid du Colombier } 573*7dd7cddfSDavid du Colombier 574*7dd7cddfSDavid du Colombier static 575*7dd7cddfSDavid du Colombier Xfid* 576*7dd7cddfSDavid du Colombier filsysstat(Filsys *fs, Xfid *x, Fid *f) 577*7dd7cddfSDavid du Colombier { 578*7dd7cddfSDavid du Colombier Fcall t; 579*7dd7cddfSDavid du Colombier 580*7dd7cddfSDavid du Colombier dostat(fs, WIN(x->f->qid), f->dir, t.stat, getclock()); 581*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, nil); 582*7dd7cddfSDavid du Colombier } 583*7dd7cddfSDavid du Colombier 584*7dd7cddfSDavid du Colombier static 585*7dd7cddfSDavid du Colombier Xfid* 586*7dd7cddfSDavid du Colombier filsyswstat(Filsys *fs, Xfid *x, Fid*) 587*7dd7cddfSDavid du Colombier { 588*7dd7cddfSDavid du Colombier Fcall t; 589*7dd7cddfSDavid du Colombier 590*7dd7cddfSDavid du Colombier return filsysrespond(fs, x, &t, Eperm); 591*7dd7cddfSDavid du Colombier } 592*7dd7cddfSDavid du Colombier 593*7dd7cddfSDavid du Colombier static 594*7dd7cddfSDavid du Colombier Fid* 595*7dd7cddfSDavid du Colombier newfid(Filsys *fs, int fid) 596*7dd7cddfSDavid du Colombier { 597*7dd7cddfSDavid du Colombier Fid *f, *ff, **fh; 598*7dd7cddfSDavid du Colombier 599*7dd7cddfSDavid du Colombier ff = nil; 600*7dd7cddfSDavid du Colombier fh = &fs->fids[fid&(Nhash-1)]; 601*7dd7cddfSDavid du Colombier for(f=*fh; f; f=f->next) 602*7dd7cddfSDavid du Colombier if(f->fid == fid) 603*7dd7cddfSDavid du Colombier return f; 604*7dd7cddfSDavid du Colombier else if(ff==nil && f->busy==FALSE) 605*7dd7cddfSDavid du Colombier ff = f; 606*7dd7cddfSDavid du Colombier if(ff){ 607*7dd7cddfSDavid du Colombier ff->fid = fid; 608*7dd7cddfSDavid du Colombier return ff; 609*7dd7cddfSDavid du Colombier } 610*7dd7cddfSDavid du Colombier f = emalloc(sizeof *f); 611*7dd7cddfSDavid du Colombier f->fid = fid; 612*7dd7cddfSDavid du Colombier f->next = *fh; 613*7dd7cddfSDavid du Colombier *fh = f; 614*7dd7cddfSDavid du Colombier return f; 615*7dd7cddfSDavid du Colombier } 616*7dd7cddfSDavid du Colombier 617*7dd7cddfSDavid du Colombier static 618*7dd7cddfSDavid du Colombier uint 619*7dd7cddfSDavid du Colombier getclock(void) 620*7dd7cddfSDavid du Colombier { 621*7dd7cddfSDavid du Colombier char buf[32]; 622*7dd7cddfSDavid du Colombier 623*7dd7cddfSDavid du Colombier seek(clockfd, 0, 0); 624*7dd7cddfSDavid du Colombier read(clockfd, buf, sizeof buf); 625*7dd7cddfSDavid du Colombier return atoi(buf); 626*7dd7cddfSDavid du Colombier } 627*7dd7cddfSDavid du Colombier 628*7dd7cddfSDavid du Colombier static 629*7dd7cddfSDavid du Colombier void 630*7dd7cddfSDavid du Colombier dostat(Filsys *fs, int id, Dirtab *dir, char *buf, uint clock) 631*7dd7cddfSDavid du Colombier { 632*7dd7cddfSDavid du Colombier Dir d; 633*7dd7cddfSDavid du Colombier 634*7dd7cddfSDavid du Colombier d.qid.path = QID(id, dir->qid); 635*7dd7cddfSDavid du Colombier d.qid.vers = 0; 636*7dd7cddfSDavid du Colombier d.mode = dir->perm; 637*7dd7cddfSDavid du Colombier d.length = 0; /* would be nice to do better */ 638*7dd7cddfSDavid du Colombier strncpy(d.name, dir->name, NAMELEN); 639*7dd7cddfSDavid du Colombier memmove(d.uid, fs->user, NAMELEN); 640*7dd7cddfSDavid du Colombier memmove(d.gid, fs->user, NAMELEN); 641*7dd7cddfSDavid du Colombier d.atime = clock; 642*7dd7cddfSDavid du Colombier d.mtime = clock; 643*7dd7cddfSDavid du Colombier convD2M(&d, buf); 644*7dd7cddfSDavid du Colombier } 645