2 #include "../port/lib.h"
6 #include "../port/error.h"
8 typedef struct Shr Shr;
18 Mhead umh; /* only lock and mount are used */
19 char *desc; /* contents of file; nil if invalid, rebuild if necessary */
40 for(m = sp->umh.mount; m != nil; m = mm) {
53 shrgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
59 devdir(c, c->qid, "#σ", 0, eve, 0555, dp);
64 for(sp = shr; sp && s; sp = sp->link)
72 mkqid(&q, sp->path, 0, c->dev ? QTFILE : QTDIR);
73 /* make sure name string continues to exist after we release lock */
74 kstrcpy(up->genbuf, sp->name, sizeof up->genbuf);
75 devdir(c, q, up->genbuf, 0, sp->owner, sp->perm & (c->dev ? ~0111 : ~0), dp);
91 if(!(spec[0] == 'c' && spec[1] == 0 || spec[0] == 0))
94 c = devattach(L'σ', spec);
103 shrlookup(char *name, ulong qidpath)
106 for(sp = shr; sp; sp = sp->link)
107 if(sp->path == qidpath || (name && strcmp(sp->name, name) == 0))
113 shrremovemnt(Shr *sp, int id)
117 wlock(&sp->umh.lock);
119 for(m = *l; m; m = m->next){
120 if(m->mountid == id){
130 wunlock(&sp->umh.lock);
133 qlock(&sp->desclock);
136 qunlock(&sp->desclock);
137 wunlock(&sp->umh.lock);
142 shrwalk(Chan *c, Chan *nc, char **name, int nname)
154 wq = smalloc(sizeof(Walkqid) + (nname - 1) * sizeof(Qid));
156 if(alloc && wq->clone != nil)
168 for(j = 0; j < nname; j++){
169 if(!(nc->qid.type & QTDIR)){
172 kstrcpy(up->errstr, Enotdir, ERRMAX);
176 if(n[0] == '.' && n[1] == 0)
178 else if(n[0] == '.' && n[1] == '.' && n[2] == 0){
179 if(nc->qid.path != 0)
181 nc->qid.type = QTDIR;
182 } else if(nc->qid.path == 0) {
184 sp = shrlookup(n, -1);
192 devpermcheck(sp->owner, sp->perm, OEXEC);
194 mkqid(&nc->qid, sp->path, 0, c->dev ? QTFILE : QTDIR);
201 sp = shrlookup(nil, nc->qid.path);
208 rlock(&sp->umh.lock);
209 for(f = sp->umh.mount; f != nil && wq2 == nil; f = f->next) {
212 wq2 = devtab[f->to->type]->walk(f->to, nil, name + j, nname - j);
215 runlock(&sp->umh.lock);
219 memmove(wq->qid + wq->nqid, wq2->qid, wq2->nqid);
220 wq->nqid += wq2->nqid;
223 wq->clone = wq2->clone;
228 wq->qid[wq->nqid++] = nc->qid;
235 kstrcpy(up->errstr, Enonexist, ERRMAX);
238 if(wq->nqid < nname) {
243 wq->clone->type = c->type;
248 shrstat(Chan *c, uchar *db, int n)
250 return devstat(c, db, n, 0, 0, shrgen);
254 shropen(Chan *c, int omode)
258 if(c->qid.type == QTDIR && omode != OREAD)
260 if(c->qid.path != 0){
266 sp = shrlookup(nil, c->qid.path);
269 if(c->qid.type == QTDIR)
271 devpermcheck(sp->owner, sp->perm, openmode(omode));
277 c->mode = openmode(omode);
284 shrunioncreate(Chan *c, char *name, int omode, ulong perm)
290 error(Enocreate); /* code below is broken */
293 sp = shrlookup(nil, c->qid.path);
303 for(m = sp->umh.mount; m != nil; m = m->next)
304 if(m->mflag & MCREATE)
309 wq = devtab[m->to->type]->walk(m->to, c, nil, 0);
318 devtab[c->type]->create(c, name, omode, perm);
324 shrcreate(Chan *c, char *name, int omode, ulong perm)
329 if(c->qid.path != 0) {
330 shrunioncreate(c, name, omode, perm);
337 if(omode & OCEXEC) /* can't happen */
338 panic("someone broke namec");
340 sp = smalloc(sizeof *sp);
341 sname = smalloc(strlen(name)+1);
350 if(sp == nil || sname == nil)
352 if(shrlookup(name, -1))
355 sp->path = qidpath++;
360 c->qid.type = QTFILE;
361 c->qid.path = sp->path;
366 kstrdup(&sp->owner, up->user);
367 sp->perm = (perm&0777) | ((perm&0444)>>2);
387 for(sp = *l; sp; sp = sp->link) {
388 if(sp->path == c->qid.path)
396 if(strcmp(sp->owner, eve) == 0 && !iseve())
398 if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) != 0 && !iseve())
409 shrwstat(Chan *c, uchar *dp, int n)
426 sp = shrlookup(nil, c->qid.path);
430 if(strcmp(sp->owner, up->user) != 0 && !iseve())
434 n = convM2D(dp, n, &d, strs);
438 sp->perm = d.mode & 0777;
440 kstrdup(&sp->owner, d.uid);
441 if(d.name && *d.name && strcmp(sp->name, d.name) != 0) {
442 if(strchr(d.name, '/') != nil)
444 kstrdup(&sp->name, d.name);
456 if(c->flag & CRCLOSE){
465 shrread(Chan *c, void *va, long n, vlong off)
474 return devdirread(c, va, n, 0, 0, shrgen);
476 if(c->qid.type & QTDIR)
477 return unionread(c, va, n);
480 sp = shrlookup(nil, c->qid.path);
486 qlock(&sp->desclock);
489 rlock(&sp->umh.lock);
490 for(f = sp->umh.mount; f != nil; f = f->next)
491 nn += 32 + strlen((char*)(f + 1));
492 s = sp->desc = smalloc(nn + 1);
494 for(f = sp->umh.mount; f != nil; f = f->next)
495 s = seprint(s, e, "%lud %s %C %lud %lld\n", f->mountid, (char*)(f + 1), devtab[f->to->mchan->type]->dc, f->to->mchan->dev, f->to->qid.path);
496 runlock(&sp->umh.lock);
498 ret = readstr(off, va, n, sp->desc);
499 qunlock(&sp->desclock);
505 shrwrite(Chan *c, void *va, long n, vlong)
508 char *buf, *p, *desc, *aname;
520 sp = shrlookup(nil, c->qid.path);
537 while(*p <= ' ' && *p != '\n')
539 if(*p == 0 || *p == '\n')
541 id = strtol(p, 0, 10);
542 if(shrremovemnt(sp, id) < 0)
554 case 'a': mode |= MAFTER; break;
555 case 'b': mode |= MBEFORE; break;
556 case 'c': mode |= MCREATE; break;
557 case 'C': mode |= MCACHE; break;
558 default: error(Ebadarg);
561 if((mode & (MAFTER|MBEFORE)) == 0 || (mode & (MAFTER|MBEFORE)) == (MAFTER|MBEFORE))
563 while(*p <= ' ' && *p != '\n')
565 if(*p == 0 || *p == '\n')
567 fd = strtol(p, &p, 10);
568 while(*p <= ' ' && *p != '\n')
570 if(*p != 0 && *p != '\n') {
572 p = strchr(desc, '\n');
577 aname = strchr(buf, '\n');
578 if(aname != nil && *++aname == 0)
580 if(strlen(desc) > 128)
583 bc = fdtochan(fd, ORDWR, 0, 1);
588 bogus.flags = mode & MCACHE;
590 bogus.authchan = nil;
592 c0 = devtab[devno('M', 0)]->attach((char*)&bogus);
596 m = smalloc(sizeof(Mount) + strlen(desc) + 1);
597 strcpy((char*)(m + 1), desc);
601 m->mountid = ++mntid;
603 wlock(&sp->umh.lock);
604 if((mode & MAFTER) != 0 && sp->umh.mount != nil) {
605 for(mm = sp->umh.mount; mm->next != nil; mm = mm->next)
609 m->next = sp->umh.mount;
612 wunlock(&sp->umh.lock);
613 qlock(&sp->desclock);
616 qunlock(&sp->desclock);