|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.