Annotation of lucent/sys/src/9/port/chan.c, revision 1.1.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.