Annotation of lucent/sys/src/9/port/chan.c, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: #include       "../port/error.h"
        !             7: 
        !             8: struct
        !             9: {
        !            10:        Lock;
        !            11:        Chan    *free;
        !            12:        int     fid;
        !            13: }chanalloc;
        !            14: 
        !            15: int
        !            16: incref(Ref *r)
        !            17: {
        !            18:        int x;
        !            19: 
        !            20:        lock(r);
        !            21:        x = ++r->ref;
        !            22:        unlock(r);
        !            23:        return x;
        !            24: }
        !            25: 
        !            26: int
        !            27: decref(Ref *r)
        !            28: {
        !            29:        int x;
        !            30: 
        !            31:        lock(r);
        !            32:        x = --r->ref;
        !            33:        unlock(r);
        !            34:        if(x < 0) 
        !            35:                panic("decref");
        !            36: 
        !            37:        return x;
        !            38: }
        !            39: 
        !            40: void
        !            41: chandevreset(void)
        !            42: {
        !            43:        int i;
        !            44: 
        !            45:        for(i=0; devchar[i]; i++)
        !            46:                (*devtab[i].reset)();
        !            47: }
        !            48: 
        !            49: void
        !            50: chandevinit(void)
        !            51: {
        !            52:        int i;
        !            53: 
        !            54:        for(i=0; devchar[i]; i++)
        !            55:                (*devtab[i].init)();
        !            56: }
        !            57: 
        !            58: Chan*
        !            59: newchan(void)
        !            60: {
        !            61:        Chan *c;
        !            62:        int nfid;
        !            63: 
        !            64:        SET(nfid);
        !            65: 
        !            66:        lock(&chanalloc);
        !            67:        c = chanalloc.free;
        !            68:        if(c)
        !            69:                chanalloc.free = c->next;
        !            70:        else{
        !            71:                nfid = ++chanalloc.fid;
        !            72:                if(nfid > 50000)
        !            73:                        panic("too many channels");
        !            74:        }
        !            75:        unlock(&chanalloc);
        !            76: 
        !            77:        if(c == 0) {
        !            78:                c = smalloc(sizeof(Chan));
        !            79:                c->fid = nfid;
        !            80:        }
        !            81: 
        !            82:        /* if you get an error before associating with a dev,
        !            83:           close calls rootclose, a nop */
        !            84:        c->type = 0;
        !            85:        c->flag = 0;
        !            86:        c->ref = 1;
        !            87:        c->dev = 0;
        !            88:        c->offset = 0;
        !            89:        c->mnt = 0;
        !            90:        c->stream = 0;
        !            91:        c->aux = 0;
        !            92:        c->mchan = 0;
        !            93:        c->mqid = (Qid){0, 0};
        !            94:        return c;
        !            95: }
        !            96: 
        !            97: void
        !            98: chanfree(Chan *c)
        !            99: {
        !           100:        c->flag = CFREE;
        !           101:        if(c->session){
        !           102:                freesession(c->session);
        !           103:                c->session = 0;
        !           104:        }
        !           105:        lock(&chanalloc);
        !           106:        c->next = chanalloc.free;
        !           107:        chanalloc.free = c;
        !           108:        unlock(&chanalloc);
        !           109: }
        !           110: 
        !           111: void
        !           112: close(Chan *c)
        !           113: {
        !           114:        if(c->flag & CFREE)
        !           115:                panic("close");
        !           116: 
        !           117:        if(decref(c) == 0){
        !           118:                if(!waserror()) {
        !           119:                        (*devtab[c->type].close)(c);
        !           120:                        poperror();
        !           121:                }
        !           122:                chanfree(c);
        !           123:        }
        !           124: }
        !           125: 
        !           126: int
        !           127: eqqid(Qid a, Qid b)
        !           128: {
        !           129:        return a.path==b.path && a.vers==b.vers;
        !           130: }
        !           131: 
        !           132: int
        !           133: eqchan(Chan *a, Chan *b, int pathonly)
        !           134: {
        !           135:        if(a->qid.path != b->qid.path)
        !           136:                return 0;
        !           137:        if(!pathonly && a->qid.vers!=b->qid.vers)
        !           138:                return 0;
        !           139:        if(a->type != b->type)
        !           140:                return 0;
        !           141:        if(a->dev != b->dev)
        !           142:                return 0;
        !           143:        return 1;
        !           144: }
        !           145: 
        !           146: int
        !           147: mount(Chan *new, Chan *old, int flag)
        !           148: {
        !           149:        Pgrp *pg;
        !           150:        Mount *nm, *f;
        !           151:        Mhead *m, **l;
        !           152:        int order;
        !           153: 
        !           154:        if(CHDIR & (old->qid.path^new->qid.path))
        !           155:                error(Emount);
        !           156: 
        !           157:        order = flag&MORDER;
        !           158: 
        !           159:        if((old->qid.path&CHDIR)==0 && order != MREPL)
        !           160:                error(Emount);
        !           161: 
        !           162:        pg = u->p->pgrp;
        !           163:        wlock(&pg->ns);
        !           164:        if(waserror()) {
        !           165:                wunlock(&pg->ns);
        !           166:                nexterror();
        !           167:        }
        !           168: 
        !           169:        l = &MOUNTH(pg, old);
        !           170:        for(m = *l; m; m = m->hash) {
        !           171:                if(eqchan(m->from, old, 1))
        !           172:                        break;
        !           173:                l = &m->hash;
        !           174:        }
        !           175: 
        !           176:        if(m == 0) {
        !           177:                m = smalloc(sizeof(Mhead));
        !           178:                m->from = old;
        !           179:                incref(old);
        !           180:                m->hash = *l;
        !           181:                *l = m;
        !           182:                if(order != MREPL) 
        !           183:                        m->mount = newmount(m, old);
        !           184:        }
        !           185: 
        !           186:        if(m->mount && order == MREPL) {
        !           187:                mountfree(m->mount);
        !           188:                m->mount = 0;
        !           189:        }
        !           190: 
        !           191:        nm = newmount(m, new);
        !           192:        if(flag & MCREATE)
        !           193:                new->flag |= CCREATE;
        !           194: 
        !           195:        if(m->mount && order == MAFTER) {
        !           196:                for(f = m->mount; f->next; f = f->next)
        !           197:                        ;
        !           198:                f->next = nm;
        !           199:        }
        !           200:        else {
        !           201:                nm->next = m->mount;
        !           202:                m->mount = nm;
        !           203:        }
        !           204: 
        !           205:        wunlock(&pg->ns);
        !           206:        poperror();
        !           207:        return nm->mountid;
        !           208: }
        !           209: 
        !           210: void
        !           211: unmount(Chan *mnt, Chan *mounted)
        !           212: {
        !           213:        Pgrp *pg;
        !           214:        Mhead *m, **l;
        !           215:        Mount *f, **p;
        !           216:        Chan *mc;
        !           217: 
        !           218:        pg = u->p->pgrp;
        !           219:        wlock(&pg->ns);
        !           220: 
        !           221:        l = &MOUNTH(pg, mnt);
        !           222:        for(m = *l; m; m = m->hash) {
        !           223:                if(eqchan(m->from, mnt, 1))
        !           224:                        break;
        !           225:                l = &m->hash;
        !           226:        }
        !           227: 
        !           228:        if(m == 0) {
        !           229:                wunlock(&pg->ns);
        !           230:                error(Eunmount);
        !           231:        }
        !           232: 
        !           233:        if(mounted == 0) {
        !           234:                *l = m->hash;
        !           235:                wunlock(&pg->ns);
        !           236:                mountfree(m->mount);
        !           237:                close(m->from);
        !           238:                free(m);
        !           239:                return;
        !           240:        }
        !           241: 
        !           242:        p = &m->mount;
        !           243:        for(f = *p; f; f = f->next) {
        !           244:                mc = f->to->mchan;
        !           245:                if(eqchan(f->to, mounted, 1) || (mc && eqchan(mc, mounted, 1))) {
        !           246:                        *p = f->next;
        !           247:                        f->next = 0;
        !           248:                        mountfree(f);
        !           249:                        if(m->mount == 0) {
        !           250:                                *l = m->hash;
        !           251:                                wunlock(&pg->ns);
        !           252:                                close(m->from);
        !           253:                                free(m);
        !           254:                                return;
        !           255:                        }
        !           256:                        wunlock(&pg->ns);
        !           257:                        return;
        !           258:                }
        !           259:                p = &f->next;
        !           260:        }
        !           261:        wunlock(&pg->ns);
        !           262:        error(Eunion);
        !           263: }
        !           264: 
        !           265: Chan*
        !           266: clone(Chan *c, Chan *nc)
        !           267: {
        !           268:        return (*devtab[c->type].clone)(c, nc);
        !           269: }
        !           270: 
        !           271: Chan*
        !           272: domount(Chan *c)
        !           273: {
        !           274:        Pgrp *pg;
        !           275:        Chan *nc;
        !           276:        Mhead *m;
        !           277: 
        !           278:        pg = u->p->pgrp;
        !           279:        rlock(&pg->ns);
        !           280:        if(waserror()) {
        !           281:                runlock(&pg->ns);
        !           282:                nexterror();
        !           283:        }
        !           284:        c->mnt = 0;
        !           285: 
        !           286:        for(m = MOUNTH(pg, c); m; m = m->hash)
        !           287:                if(eqchan(m->from, c, 1)) {
        !           288:                        nc = clone(m->mount->to, 0);
        !           289:                        nc->mnt = m->mount;
        !           290:                        nc->mountid = m->mount->mountid;
        !           291:                        close(c);
        !           292:                        c = nc; 
        !           293:                        break;                  
        !           294:                }
        !           295: 
        !           296:        poperror();
        !           297:        runlock(&pg->ns);
        !           298:        return c;
        !           299: }
        !           300: 
        !           301: Chan*
        !           302: undomount(Chan *c)
        !           303: {
        !           304:        Pgrp *pg;
        !           305:        Mhead **h, **he, *f;
        !           306:        Mount *t;
        !           307: 
        !           308:        pg = u->p->pgrp;
        !           309:        rlock(&pg->ns);
        !           310:        if(waserror()) {
        !           311:                runlock(&pg->ns);
        !           312:                nexterror();
        !           313:        }
        !           314: 
        !           315:        he = &pg->mnthash[MNTHASH];
        !           316:        for(h = pg->mnthash; h < he; h++) {
        !           317:                for(f = *h; f; f = f->hash) {
        !           318:                        for(t = f->mount; t; t = t->next) {
        !           319:                                if(eqchan(c, t->to, 1)) {
        !           320:                                        close(c);
        !           321:                                        c = clone(t->head->from, 0);
        !           322:                                        break;
        !           323:                                }
        !           324:                        }
        !           325:                }
        !           326:        }
        !           327:        poperror();
        !           328:        runlock(&pg->ns);
        !           329:        return c;
        !           330: }
        !           331: 
        !           332: Chan*
        !           333: walk(Chan *ac, char *name, int domnt)
        !           334: {
        !           335:        Pgrp *pg;
        !           336:        Chan *c = 0;
        !           337:        Mount *f;
        !           338:        int dotdot;
        !           339: 
        !           340:        if(*name == '\0')
        !           341:                return ac;
        !           342: 
        !           343:        dotdot = 0;
        !           344:        if(name[0] == '.')
        !           345:        if(name[1] == '.')
        !           346:        if(name[2] == '\0') {
        !           347:                ac = undomount(ac);
        !           348:                dotdot = 1;
        !           349:        }
        !           350: 
        !           351:        if((*devtab[ac->type].walk)(ac, name) != 0) {
        !           352:                if(dotdot)
        !           353:                        ac = undomount(ac);
        !           354:                if(domnt)
        !           355:                        ac = domount(ac);
        !           356:                return ac;
        !           357:        }
        !           358: 
        !           359:        if(ac->mnt == 0) 
        !           360:                return 0;
        !           361: 
        !           362:        pg = u->p->pgrp;
        !           363:        rlock(&pg->ns);
        !           364:        if(waserror()) {
        !           365:                runlock(&pg->ns);
        !           366:                if(c)
        !           367:                        close(c);
        !           368:                nexterror();
        !           369:        }
        !           370:        for(f = ac->mnt; f; f = f->next) {
        !           371:                c = clone(f->to, 0);
        !           372:                if((*devtab[c->type].walk)(c, name) != 0)
        !           373:                        break;
        !           374:                close(c);
        !           375:                c = 0;
        !           376:        }
        !           377:        poperror();
        !           378:        runlock(&pg->ns);
        !           379: 
        !           380:        if(c) {
        !           381:                if(dotdot)
        !           382:                        c = undomount(c);
        !           383:                c->mnt = 0;
        !           384:                if(domnt) {
        !           385:                        if(waserror()) {
        !           386:                                close(c);
        !           387:                                nexterror();
        !           388:                        }
        !           389:                        c = domount(c);
        !           390:                        poperror();
        !           391:                }
        !           392:                close(ac);
        !           393:        }
        !           394:        return c;       
        !           395: }
        !           396: 
        !           397: /*
        !           398:  * c is a mounted non-creatable directory.  find a creatable one.
        !           399:  */
        !           400: Chan*
        !           401: createdir(Chan *c)
        !           402: {
        !           403:        Pgrp *pg;
        !           404:        Chan *nc;
        !           405:        Mount *f;
        !           406: 
        !           407:        pg = u->p->pgrp;
        !           408:        rlock(&pg->ns);
        !           409:        if(waserror()) {
        !           410:                runlock(&pg->ns);
        !           411:                nexterror();
        !           412:        }
        !           413:        for(f = c->mnt; f; f = f->next) {
        !           414:                if(f->to->flag&CCREATE) {
        !           415:                        nc = clone(f->to, 0);
        !           416:                        nc->mnt = f;
        !           417:                        runlock(&pg->ns);
        !           418:                        poperror();
        !           419:                        close(c);
        !           420:                        return nc;
        !           421:                }
        !           422:        }
        !           423:        error(Enocreate);
        !           424:        return 0;               /* not reached */
        !           425: }
        !           426: 
        !           427: void
        !           428: saveregisters(void)
        !           429: {
        !           430: }
        !           431: 
        !           432: /*
        !           433:  * Turn a name into a channel.
        !           434:  * &name[0] is known to be a valid address.  It may be a kernel address.
        !           435:  */
        !           436: Chan*
        !           437: namec(char *name, int amode, int omode, ulong perm)
        !           438: {
        !           439:        Chan *c, *nc, *cc;
        !           440:        int t;
        !           441:        Rune r;
        !           442:        int mntok, isdot;
        !           443:        char *p;
        !           444:        char *elem;
        !           445:        char createerr[ERRLEN];
        !           446: 
        !           447:        if(name[0] == 0)
        !           448:                error(Enonexist);
        !           449: 
        !           450:        /*
        !           451:         * Make sure all of name is o.k.  first byte is validated
        !           452:         * externally so if it's a kernel address we know it's o.k.
        !           453:         */
        !           454:        if(!((ulong)name & KZERO)){
        !           455:                p = name;
        !           456:                t = BY2PG-((ulong)p&(BY2PG-1));
        !           457:                while(vmemchr(p, 0, t) == 0){
        !           458:                        p += t;
        !           459:                        t = BY2PG;
        !           460:                }
        !           461:        }
        !           462: 
        !           463:        elem = u->elem;
        !           464:        mntok = 1;
        !           465:        isdot = 0;
        !           466:        if(name[0] == '/') {
        !           467:                c = clone(u->slash, 0);
        !           468:                /*
        !           469:                 * Skip leading slashes.
        !           470:                 */
        !           471:                name = skipslash(name);
        !           472:        }
        !           473:        else
        !           474:        if(name[0] == '#') {
        !           475:                mntok = 0;
        !           476:                name++;
        !           477:                name += chartorune(&r, name);
        !           478:                if(r == 'M')
        !           479:                        error(Enonexist);
        !           480:                t = devno(r, 1);
        !           481:                if(t == -1)
        !           482:                        error(Ebadsharp);
        !           483:                if(*name == '/'){
        !           484:                        name = skipslash(name);
        !           485:                        elem[0]=0;
        !           486:                }else
        !           487:                        name = nextelem(name, elem);
        !           488:                c = (*devtab[t].attach)(elem);
        !           489:        }
        !           490:        else {
        !           491:                c = clone(u->dot, 0);
        !           492:                name = skipslash(name); /* eat leading ./ */
        !           493:                if(*name == 0)
        !           494:                        isdot = 1;
        !           495:        }
        !           496: 
        !           497:        if(waserror()){
        !           498:                close(c);
        !           499:                nexterror();
        !           500:        }
        !           501: 
        !           502:        name = nextelem(name, elem);
        !           503: 
        !           504:        /*
        !           505:         *  If mounting, don't follow the mount entry for root or the
        !           506:         *  current directory.
        !           507:         */
        !           508:        if(mntok && !isdot && !(amode==Amount && elem[0]==0))
        !           509:                c = domount(c);                 /* see case Atodir below */
        !           510: 
        !           511:        /*
        !           512:         * How to treat the last element of the name depends on the operation.
        !           513:         * Therefore do all but the last element by the easy algorithm.
        !           514:         */
        !           515:        while(*name){
        !           516:                if((nc=walk(c, elem, mntok)) == 0)
        !           517:                        error(Enonexist);
        !           518:                c = nc;
        !           519:                name = nextelem(name, elem);
        !           520:        }
        !           521: 
        !           522:        /*
        !           523:         * Last element; act according to type of access.
        !           524:         */
        !           525:        switch(amode){
        !           526:        case Aaccess:
        !           527:                if(isdot)
        !           528:                        c = domount(c);
        !           529:                else{
        !           530:                        if((nc=walk(c, elem, mntok)) == 0)
        !           531:                                error(Enonexist);
        !           532:                        c = nc;
        !           533:                }
        !           534:                break;
        !           535: 
        !           536:        case Atodir:
        !           537:                /*
        !           538:                 * Directories (e.g. for cd) are left before the mount point,
        !           539:                 * so one may mount on / or . and see the effect.
        !           540:                 */
        !           541:                if((nc=walk(c, elem, 0)) == 0)
        !           542:                        error(Enonexist);
        !           543:                c = nc;
        !           544:                if(!(c->qid.path & CHDIR))
        !           545:                        error(Enotdir);
        !           546:                break;
        !           547: 
        !           548:        case Aopen:
        !           549:                if(isdot)
        !           550:                        c = domount(c);
        !           551:                else{
        !           552:                        if((nc=walk(c, elem, mntok)) == 0)
        !           553:                                error(Enonexist);
        !           554:                        c = nc;
        !           555:                }
        !           556:        Open:
        !           557:                /* else error() in open has wrong value of c saved */
        !           558:                saveregisters();        
        !           559:                c = (*devtab[c->type].open)(c, omode);
        !           560:                if(omode & OCEXEC)
        !           561:                        c->flag |= CCEXEC;
        !           562:                if(omode & ORCLOSE)
        !           563:                        c->flag |= CRCLOSE;
        !           564:                break;
        !           565: 
        !           566:        case Amount:
        !           567:                /*
        !           568:                 * When mounting on an already mounted upon directory, one wants
        !           569:                 * subsequent mounts to be attached to the original directory, not
        !           570:                 * the replacement.
        !           571:                 */
        !           572:                if((nc=walk(c, elem, 0)) == 0)
        !           573:                        error(Enonexist);
        !           574:                c = nc;
        !           575:                break;
        !           576: 
        !           577:        case Acreate:
        !           578:                if(isdot)
        !           579:                        error(Eisdir);
        !           580: 
        !           581:                /*
        !           582:                 *  Walk the element before trying to create it
        !           583:                 *  to see if it exists.  We clone the channel
        !           584:                 *  first, just in case someone is trying to
        !           585:                 *  use clwalk outside the kernel.
        !           586:                 */
        !           587:                cc = clone(c, 0);
        !           588:                if(waserror()){
        !           589:                        close(cc);
        !           590:                        nexterror();
        !           591:                }
        !           592:                nameok(elem);
        !           593:                if((nc=walk(cc, elem, 1)) != 0){
        !           594:                        poperror();
        !           595:                        close(c);
        !           596:                        c = nc;
        !           597:                        omode |= OTRUNC;
        !           598:                        goto Open;
        !           599:                }
        !           600:                close(cc);
        !           601:                poperror();
        !           602: 
        !           603:                /*
        !           604:                 *  the file didn't exist, try the create
        !           605:                 */
        !           606:                if(c->mnt && !(c->flag&CCREATE))
        !           607:                        c = createdir(c);
        !           608: 
        !           609:                /*
        !           610:                 *  protect against the open/create race. This is not a complete
        !           611:                 *  fix. It just reduces the window.
        !           612:                 */
        !           613:                if(waserror()) {
        !           614:                        strcpy(createerr, u->error);
        !           615:                        nc = walk(c, elem, 1);
        !           616:                        if(nc == 0)
        !           617:                                error(createerr);
        !           618:                        c = nc;
        !           619:                        omode |= OTRUNC;
        !           620:                        goto Open;
        !           621:                }
        !           622:                (*devtab[c->type].create)(c, elem, omode, perm);
        !           623:                if(omode & OCEXEC)
        !           624:                        c->flag |= CCEXEC;
        !           625:                poperror();
        !           626:                break;
        !           627: 
        !           628:        default:
        !           629:                panic("unknown namec access %d\n", amode);
        !           630:        }
        !           631:        poperror();
        !           632:        return c;
        !           633: }
        !           634: 
        !           635: /*
        !           636:  * name[0] is addressable.
        !           637:  */
        !           638: char*
        !           639: skipslash(char *name)
        !           640: {
        !           641:     Again:
        !           642:        while(*name == '/')
        !           643:                name++;
        !           644:        if(*name=='.' && (name[1]==0 || name[1]=='/')){
        !           645:                name++;
        !           646:                goto Again;
        !           647:        }
        !           648:        return name;
        !           649: }
        !           650: 
        !           651: char isfrog[256]={
        !           652:        /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1,
        !           653:        /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1,
        !           654:        /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1,
        !           655:        /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1,
        !           656:        [' ']   1,
        !           657:        ['/']   1,
        !           658:        [0x7f]  1,
        !           659: };
        !           660: 
        !           661: void
        !           662: nameok(char *elem)
        !           663: {
        !           664:        char *eelem;
        !           665: 
        !           666:        eelem = elem+NAMELEN;
        !           667:        while(*elem) {
        !           668:                if(isfrog[*(uchar*)elem])
        !           669:                        error(Ebadchar);
        !           670:                elem++;
        !           671:                if(elem >= eelem)
        !           672:                        error(Efilename);
        !           673:        }
        !           674: }
        !           675: 
        !           676: /*
        !           677:  * name[0] should not be a slash.
        !           678:  */
        !           679: char*
        !           680: nextelem(char *name, char *elem)
        !           681: {
        !           682:        int w;
        !           683:        char *nend;
        !           684:        Rune r;
        !           685: 
        !           686:        if(*name == '/')
        !           687:                error(Efilename);
        !           688:        nend = utfrune(name, '/');
        !           689:        if(nend == 0)
        !           690:                nend = strchr(name, 0);
        !           691:        w = nend-name;
        !           692:        if(w >= NAMELEN)
        !           693:                error(Efilename);
        !           694:        memmove(elem, name, w);
        !           695:        elem[w] = 0;
        !           696:        while(name < nend){
        !           697:                name += chartorune(&r, name);
        !           698:                if(r<sizeof(isfrog) && isfrog[r])
        !           699:                        error(Ebadchar);
        !           700:        }
        !           701:        return skipslash(name);
        !           702: }
        !           703: 
        !           704: void
        !           705: isdir(Chan *c)
        !           706: {
        !           707:        if(c->qid.path & CHDIR)
        !           708:                return;
        !           709:        error(Enotdir);
        !           710: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.