chan.c (35215B)
1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "error.h" 7 8 int chandebug=0; /* toggled by sysr1 */ 9 #define DBG if(chandebug)iprint 10 11 enum 12 { 13 PATHSLOP = 20, 14 PATHMSLOP = 20, 15 }; 16 17 struct 18 { 19 Lock lk; 20 int fid; 21 Chan *free; 22 Chan *list; 23 }chanalloc; 24 25 typedef struct Elemlist Elemlist; 26 27 struct Elemlist 28 { 29 char *aname; /* original name */ 30 char *name; /* copy of name, so '/' can be overwritten */ 31 int nelems; 32 char **elems; 33 int *off; 34 int mustbedir; 35 int nerror; 36 int prefix; 37 }; 38 39 #define SEP(c) ((c) == 0 || (c) == '/') 40 41 /*static*/ void 42 dumpmount(void) /* DEBUGGING */ 43 { 44 Pgrp *pg; 45 Mount *t; 46 Mhead **h, **he, *f; 47 48 if(up == nil){ 49 print("no process for dumpmount\n"); 50 return; 51 } 52 pg = up->pgrp; 53 if(pg == nil){ 54 print("no pgrp for dumpmount\n"); 55 return; 56 } 57 rlock(&pg->ns); 58 if(waserror()){ 59 runlock(&pg->ns); 60 nexterror(); 61 } 62 63 he = &pg->mnthash[MNTHASH]; 64 for(h = pg->mnthash; h < he; h++){ 65 for(f = *h; f; f = f->hash){ 66 print("head: %#p: %s %#llux.%lud %C %lud -> \n", f, 67 f->from->path->s, f->from->qid.path, 68 f->from->qid.vers, devtab[f->from->type]->dc, 69 f->from->dev); 70 for(t = f->mount; t; t = t->next) 71 print("\t%#p: %s (umh %#p) (path %#.8llux dev %C %lud)\n", t, t->to->path->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev); 72 } 73 } 74 poperror(); 75 runlock(&pg->ns); 76 } 77 78 char* 79 chanpath(Chan *c) 80 { 81 if(c == nil) 82 return "<nil chan>"; 83 if(c->path == nil) 84 return "<nil path>"; 85 if(c->path->s == nil) 86 return "<nil path.s>"; 87 return c->path->s; 88 } 89 90 int 91 isdotdot(char *p) 92 { 93 return p[0]=='.' && p[1]=='.' && p[2]=='\0'; 94 } 95 96 long 97 incref(Ref *r) 98 { 99 long x; 100 101 lock(&r->lk); 102 x = ++r->ref; 103 unlock(&r->lk); 104 return x; 105 } 106 107 long 108 decref(Ref *r) 109 { 110 long x; 111 112 lock(&r->lk); 113 x = --r->ref; 114 unlock(&r->lk); 115 if(x < 0) 116 panic("decref pc=%#p", getcallerpc(&r)); 117 118 return x; 119 } 120 121 /* 122 * Rather than strncpy, which zeros the rest of the buffer, kstrcpy 123 * truncates if necessary, always zero terminates, does not zero fill, 124 * and puts ... at the end of the string if it's too long. Usually used to 125 * save a string in up->genbuf; 126 */ 127 void 128 kstrcpy(char *s, char *t, int ns) 129 { 130 int nt; 131 132 nt = strlen(t); 133 if(nt+1 <= ns){ 134 memmove(s, t, nt+1); 135 return; 136 } 137 /* too long */ 138 if(ns < 4){ 139 /* but very short! */ 140 strncpy(s, t, ns); 141 return; 142 } 143 /* truncate with ... at character boundary (very rare case) */ 144 memmove(s, t, ns-4); 145 ns -= 4; 146 s[ns] = '\0'; 147 /* look for first byte of UTF-8 sequence by skipping continuation bytes */ 148 while(ns>0 && (s[--ns]&0xC0)==0x80) 149 ; 150 strcpy(s+ns, "..."); 151 } 152 153 int 154 emptystr(char *s) 155 { 156 if(s == nil) 157 return 1; 158 if(s[0] == '\0') 159 return 1; 160 return 0; 161 } 162 163 /* 164 * Atomically replace *p with copy of s 165 */ 166 void 167 kstrdup(char **p, char *s) 168 { 169 int n; 170 char *t, *prev; 171 172 n = strlen(s)+1; 173 /* if it's a user, we can wait for memory; if not, something's very wrong */ 174 if(up){ 175 t = smalloc(n); 176 setmalloctag(t, getcallerpc(&p)); 177 }else{ 178 t = malloc(n); 179 if(t == nil) 180 panic("kstrdup: no memory"); 181 } 182 memmove(t, s, n); 183 prev = *p; 184 *p = t; 185 free(prev); 186 } 187 188 void 189 chandevreset(void) 190 { 191 int i; 192 193 todinit(); /* avoid later reentry causing infinite recursion */ 194 for(i=0; devtab[i] != nil; i++) 195 devtab[i]->reset(); 196 } 197 198 void 199 chandevinit(void) 200 { 201 int i; 202 203 for(i=0; devtab[i] != nil; i++) 204 devtab[i]->init(); 205 } 206 207 void 208 chandevshutdown(void) 209 { 210 int i; 211 212 /* shutdown in reverse order */ 213 for(i=0; devtab[i] != nil; i++) 214 ; 215 for(i--; i >= 0; i--) 216 devtab[i]->shutdown(); 217 } 218 219 Chan* 220 newchan(void) 221 { 222 Chan *c; 223 224 lock(&chanalloc.lk); 225 c = chanalloc.free; 226 if(c != 0) 227 chanalloc.free = c->next; 228 unlock(&chanalloc.lk); 229 230 if(c == nil){ 231 c = smalloc(sizeof(Chan)); 232 lock(&chanalloc.lk); 233 c->fid = ++chanalloc.fid; 234 c->link = chanalloc.list; 235 chanalloc.list = c; 236 unlock(&chanalloc.lk); 237 } 238 239 /* if you get an error before associating with a dev, 240 close calls rootclose, a nop */ 241 c->type = 0; 242 c->flag = 0; 243 c->ref.ref = 1; 244 c->dev = 0; 245 c->offset = 0; 246 c->devoffset = 0; 247 c->iounit = 0; 248 c->umh = 0; 249 c->uri = 0; 250 c->dri = 0; 251 c->aux = 0; 252 c->mchan = 0; 253 c->mcp = 0; 254 c->mux = 0; 255 memset(&c->mqid, 0, sizeof(c->mqid)); 256 c->path = 0; 257 c->ismtpt = 0; 258 259 return c; 260 } 261 262 Ref npath; 263 264 Path* 265 newpath(char *s) 266 { 267 int i; 268 Path *p; 269 270 p = smalloc(sizeof(Path)); 271 i = strlen(s); 272 p->len = i; 273 p->alen = i+PATHSLOP; 274 p->s = smalloc(p->alen); 275 memmove(p->s, s, i+1); 276 p->ref.ref = 1; 277 incref(&npath); 278 279 /* 280 * Cannot use newpath for arbitrary names because the mtpt 281 * array will not be populated correctly. The names #/ and / are 282 * allowed, but other names with / in them draw warnings. 283 */ 284 if(strchr(s, '/') && strcmp(s, "#/") != 0 && strcmp(s, "/") != 0) 285 print("newpath: %s from %#p\n", s, getcallerpc(&s)); 286 287 p->mlen = 1; 288 p->malen = PATHMSLOP; 289 p->mtpt = smalloc(p->malen*sizeof p->mtpt[0]); 290 return p; 291 } 292 293 static Path* 294 copypath(Path *p) 295 { 296 int i; 297 Path *pp; 298 299 pp = smalloc(sizeof(Path)); 300 pp->ref.ref = 1; 301 incref(&npath); 302 DBG("copypath %s %p => %p\n", p->s, p, pp); 303 304 pp->len = p->len; 305 pp->alen = p->alen; 306 pp->s = smalloc(p->alen); 307 memmove(pp->s, p->s, p->len+1); 308 309 pp->mlen = p->mlen; 310 pp->malen = p->malen; 311 pp->mtpt = smalloc(p->malen*sizeof pp->mtpt[0]); 312 for(i=0; i<pp->mlen; i++){ 313 pp->mtpt[i] = p->mtpt[i]; 314 if(pp->mtpt[i]) 315 incref(&pp->mtpt[i]->ref); 316 } 317 318 return pp; 319 } 320 321 void 322 pathclose(Path *p) 323 { 324 int i; 325 326 if(p == nil) 327 return; 328 //XXX 329 DBG("pathclose %p %s ref=%ld =>", p, p->s, p->ref.ref); 330 for(i=0; i<p->mlen; i++) 331 DBG(" %p", p->mtpt[i]); 332 DBG("\n"); 333 334 if(decref(&p->ref)) 335 return; 336 decref(&npath); 337 free(p->s); 338 for(i=0; i<p->mlen; i++) 339 if(p->mtpt[i]) 340 cclose(p->mtpt[i]); 341 free(p->mtpt); 342 free(p); 343 } 344 345 /* 346 * In place, rewrite name to compress multiple /, eliminate ., and process .. 347 * (Really only called to remove a trailing .. that has been added. 348 * Otherwise would need to update n->mtpt as well.) 349 */ 350 static void 351 fixdotdotname(Path *p) 352 { 353 char *r; 354 355 if(p->s[0] == '#'){ 356 r = strchr(p->s, '/'); 357 if(r == nil) 358 return; 359 cleanname(r); 360 361 /* 362 * The correct name is #i rather than #i/, 363 * but the correct name of #/ is #/. 364 */ 365 if(strcmp(r, "/")==0 && p->s[1] != '/') 366 *r = '\0'; 367 }else 368 cleanname(p->s); 369 p->len = strlen(p->s); 370 } 371 372 static Path* 373 uniquepath(Path *p) 374 { 375 Path *new; 376 377 if(p->ref.ref > 1){ 378 /* copy on write */ 379 new = copypath(p); 380 pathclose(p); 381 p = new; 382 } 383 return p; 384 } 385 386 /*static*/ Path* 387 addelem(Path *p, char *s, Chan *from) 388 { 389 char *t; 390 int a, i; 391 Chan *c, **tt; 392 393 if(s[0]=='.' && s[1]=='\0') 394 return p; 395 396 p = uniquepath(p); 397 398 i = strlen(s); 399 if(p->len+1+i+1 > p->alen){ 400 a = p->len+1+i+1 + PATHSLOP; 401 t = smalloc(a); 402 memmove(t, p->s, p->len+1); 403 free(p->s); 404 p->s = t; 405 p->alen = a; 406 } 407 /* don't insert extra slash if one is present */ 408 if(p->len>0 && p->s[p->len-1]!='/' && s[0]!='/') 409 p->s[p->len++] = '/'; 410 memmove(p->s+p->len, s, i+1); 411 p->len += i; 412 if(isdotdot(s)){ 413 fixdotdotname(p); 414 DBG("addelem %s .. => rm %p\n", p->s, p->mtpt[p->mlen-1]); 415 if(p->mlen>1 && (c = p->mtpt[--p->mlen])){ 416 p->mtpt[p->mlen] = nil; 417 cclose(c); 418 } 419 }else{ 420 if(p->mlen >= p->malen){ 421 p->malen = p->mlen+1+PATHMSLOP; 422 tt = smalloc(p->malen*sizeof tt[0]); 423 memmove(tt, p->mtpt, p->mlen*sizeof tt[0]); 424 free(p->mtpt); 425 p->mtpt = tt; 426 } 427 DBG("addelem %s %s => add %p\n", p->s, s, from); 428 p->mtpt[p->mlen++] = from; 429 if(from) 430 incref(&from->ref); 431 } 432 return p; 433 } 434 435 void 436 chanfree(Chan *c) 437 { 438 c->flag = CFREE; 439 440 if(c->dirrock != nil){ 441 free(c->dirrock); 442 c->dirrock = 0; 443 c->nrock = 0; 444 c->mrock = 0; 445 } 446 if(c->umh != nil){ 447 putmhead(c->umh); 448 c->umh = nil; 449 } 450 if(c->umc != nil){ 451 cclose(c->umc); 452 c->umc = nil; 453 } 454 if(c->mux != nil){ 455 muxclose(c->mux); 456 c->mux = nil; 457 } 458 if(c->mchan != nil){ 459 cclose(c->mchan); 460 c->mchan = nil; 461 } 462 463 pathclose(c->path); 464 c->path = nil; 465 466 lock(&chanalloc.lk); 467 c->next = chanalloc.free; 468 chanalloc.free = c; 469 unlock(&chanalloc.lk); 470 } 471 472 void 473 cclose(Chan *c) 474 { 475 if(c->flag&CFREE) 476 panic("cclose %#p", getcallerpc(&c)); 477 478 DBG("cclose %p name=%s ref=%ld\n", c, c->path->s, c->ref.ref); 479 if(decref(&c->ref)) 480 return; 481 482 if(!waserror()){ 483 devtab[c->type]->close(c); 484 poperror(); 485 } 486 chanfree(c); 487 } 488 489 /* 490 * Queue a chan to be closed by one of the clunk procs. 491 */ 492 struct { 493 Chan *head; 494 Chan *tail; 495 int nqueued; 496 int nclosed; 497 Lock l; 498 QLock q; 499 Rendez r; 500 } clunkq; 501 void closeproc(void*); 502 503 void 504 ccloseq(Chan *c) 505 { 506 if(c->flag&CFREE) 507 panic("cclose %#p", getcallerpc(&c)); 508 509 DBG("ccloseq %p name=%s ref=%ld\n", c, c->path->s, c->ref.ref); 510 511 if(decref(&c->ref)) 512 return; 513 514 lock(&clunkq.l); 515 clunkq.nqueued++; 516 c->next = nil; 517 if(clunkq.head) 518 clunkq.tail->next = c; 519 else 520 clunkq.head = c; 521 clunkq.tail = c; 522 unlock(&clunkq.l); 523 524 if(!wakeup(&clunkq.r)) 525 kproc("closeproc", closeproc, nil); 526 } 527 528 static int 529 clunkwork(void *v) 530 { 531 return clunkq.head != nil; 532 } 533 534 void 535 closeproc(void *v) 536 { 537 Chan *c; 538 539 for(;;){ 540 qlock(&clunkq.q); 541 if(clunkq.head == nil){ 542 if(!waserror()){ 543 tsleep(&clunkq.r, clunkwork, nil, 5000); 544 poperror(); 545 } 546 if(clunkq.head == nil){ 547 qunlock(&clunkq.q); 548 pexit("no work", 1); 549 } 550 } 551 lock(&clunkq.l); 552 c = clunkq.head; 553 clunkq.head = c->next; 554 clunkq.nclosed++; 555 unlock(&clunkq.l); 556 qunlock(&clunkq.q); 557 if(!waserror()){ 558 devtab[c->type]->close(c); 559 poperror(); 560 } 561 chanfree(c); 562 } 563 } 564 565 /* 566 * Make sure we have the only copy of c. (Copy on write.) 567 */ 568 Chan* 569 cunique(Chan *c) 570 { 571 Chan *nc; 572 573 if(c->ref.ref != 1){ 574 nc = cclone(c); 575 cclose(c); 576 c = nc; 577 } 578 579 return c; 580 } 581 582 int 583 eqqid(Qid a, Qid b) 584 { 585 return a.path==b.path && a.vers==b.vers; 586 } 587 588 int 589 eqchan(Chan *a, Chan *b, int skipvers) 590 { 591 if(a->qid.path != b->qid.path) 592 return 0; 593 if(!skipvers && a->qid.vers!=b->qid.vers) 594 return 0; 595 if(a->type != b->type) 596 return 0; 597 if(a->dev != b->dev) 598 return 0; 599 return 1; 600 } 601 602 int 603 eqchantdqid(Chan *a, int type, int dev, Qid qid, int skipvers) 604 { 605 if(a->qid.path != qid.path) 606 return 0; 607 if(!skipvers && a->qid.vers!=qid.vers) 608 return 0; 609 if(a->type != type) 610 return 0; 611 if(a->dev != dev) 612 return 0; 613 return 1; 614 } 615 616 Mhead* 617 newmhead(Chan *from) 618 { 619 Mhead *mh; 620 621 mh = smalloc(sizeof(Mhead)); 622 mh->ref.ref = 1; 623 mh->from = from; 624 incref(&from->ref); 625 return mh; 626 } 627 628 int 629 cmount(Chan **newp, Chan *old, int flag, char *spec) 630 { 631 int order, flg; 632 Chan *new; 633 Mhead *m, **l, *mh; 634 Mount *nm, *f, *um, **h; 635 Pgrp *pg; 636 637 if(QTDIR & (old->qid.type^(*newp)->qid.type)) 638 error(Emount); 639 640 if(old->umh) 641 print("cmount: unexpected umh, caller %#p\n", getcallerpc(&newp)); 642 643 order = flag&MORDER; 644 645 if((old->qid.type&QTDIR)==0 && order != MREPL) 646 error(Emount); 647 648 new = *newp; 649 mh = new->umh; 650 651 /* 652 * Not allowed to bind when the old directory is itself a union. 653 * (Maybe it should be allowed, but I don't see what the semantics 654 * would be.) 655 * 656 * We need to check mh->mount->next to tell unions apart from 657 * simple mount points, so that things like 658 * mount -c fd /root 659 * bind -c /root / 660 * work. 661 * 662 * The check of mount->mflag allows things like 663 * mount fd /root 664 * bind -c /root / 665 * 666 * This is far more complicated than it should be, but I don't 667 * see an easier way at the moment. 668 */ 669 if((flag&MCREATE) && mh && mh->mount 670 && (mh->mount->next || !(mh->mount->mflag&MCREATE))) 671 error(Emount); 672 673 pg = up->pgrp; 674 wlock(&pg->ns); 675 676 l = &MOUNTH(pg, old->qid); 677 for(m = *l; m; m = m->hash){ 678 if(eqchan(m->from, old, 1)) 679 break; 680 l = &m->hash; 681 } 682 683 if(m == nil){ 684 /* 685 * nothing mounted here yet. create a mount 686 * head and add to the hash table. 687 */ 688 m = newmhead(old); 689 *l = m; 690 691 /* 692 * if this is a union mount, add the old 693 * node to the mount chain. 694 */ 695 if(order != MREPL) 696 m->mount = newmount(m, old, 0, 0); 697 } 698 wlock(&m->lock); 699 if(waserror()){ 700 wunlock(&m->lock); 701 nexterror(); 702 } 703 wunlock(&pg->ns); 704 705 nm = newmount(m, new, flag, spec); 706 if(mh != nil && mh->mount != nil){ 707 /* 708 * copy a union when binding it onto a directory 709 */ 710 flg = order; 711 if(order == MREPL) 712 flg = MAFTER; 713 h = &nm->next; 714 um = mh->mount; 715 for(um = um->next; um; um = um->next){ 716 f = newmount(m, um->to, flg, um->spec); 717 *h = f; 718 h = &f->next; 719 } 720 } 721 722 if(m->mount && order == MREPL){ 723 mountfree(m->mount); 724 m->mount = 0; 725 } 726 727 if(flag & MCREATE) 728 nm->mflag |= MCREATE; 729 730 if(m->mount && order == MAFTER){ 731 for(f = m->mount; f->next; f = f->next) 732 ; 733 f->next = nm; 734 }else{ 735 for(f = nm; f->next; f = f->next) 736 ; 737 f->next = m->mount; 738 m->mount = nm; 739 } 740 741 wunlock(&m->lock); 742 poperror(); 743 return nm->mountid; 744 } 745 746 void 747 cunmount(Chan *mnt, Chan *mounted) 748 { 749 Pgrp *pg; 750 Mhead *m, **l; 751 Mount *f, **p; 752 753 if(mnt->umh) /* should not happen */ 754 print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh); 755 756 /* 757 * It _can_ happen that mounted->umh is non-nil, 758 * because mounted is the result of namec(Aopen) 759 * (see sysfile.c:/^sysunmount). 760 * If we open a union directory, it will have a umh. 761 * Although surprising, this is okay, since the 762 * cclose will take care of freeing the umh. 763 */ 764 765 pg = up->pgrp; 766 wlock(&pg->ns); 767 768 l = &MOUNTH(pg, mnt->qid); 769 for(m = *l; m; m = m->hash){ 770 if(eqchan(m->from, mnt, 1)) 771 break; 772 l = &m->hash; 773 } 774 775 if(m == 0){ 776 wunlock(&pg->ns); 777 error(Eunmount); 778 } 779 780 wlock(&m->lock); 781 if(mounted == 0){ 782 *l = m->hash; 783 wunlock(&pg->ns); 784 mountfree(m->mount); 785 m->mount = nil; 786 cclose(m->from); 787 wunlock(&m->lock); 788 putmhead(m); 789 return; 790 } 791 792 p = &m->mount; 793 for(f = *p; f; f = f->next){ 794 /* BUG: Needs to be 2 pass */ 795 if(eqchan(f->to, mounted, 1) || 796 (f->to->mchan && eqchan(f->to->mchan, mounted, 1))){ 797 *p = f->next; 798 f->next = 0; 799 mountfree(f); 800 if(m->mount == nil){ 801 *l = m->hash; 802 cclose(m->from); 803 wunlock(&m->lock); 804 wunlock(&pg->ns); 805 putmhead(m); 806 return; 807 } 808 wunlock(&m->lock); 809 wunlock(&pg->ns); 810 return; 811 } 812 p = &f->next; 813 } 814 wunlock(&m->lock); 815 wunlock(&pg->ns); 816 error(Eunion); 817 } 818 819 Chan* 820 cclone(Chan *c) 821 { 822 Chan *nc; 823 Walkqid *wq; 824 825 wq = devtab[c->type]->walk(c, nil, nil, 0); 826 if(wq == nil) 827 error("clone failed"); 828 nc = wq->clone; 829 free(wq); 830 nc->path = c->path; 831 if(c->path) 832 incref(&c->path->ref); 833 return nc; 834 } 835 836 /* also used by sysfile.c:/^mountfix */ 837 int 838 findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid) 839 { 840 Pgrp *pg; 841 Mhead *m; 842 843 pg = up->pgrp; 844 rlock(&pg->ns); 845 for(m = MOUNTH(pg, qid); m; m = m->hash){ 846 rlock(&m->lock); 847 if(m->from == nil){ 848 print("m %p m->from 0\n", m); 849 runlock(&m->lock); 850 continue; 851 } 852 if(eqchantdqid(m->from, type, dev, qid, 1)){ 853 runlock(&pg->ns); 854 if(mp != nil){ 855 incref(&m->ref); 856 if(*mp != nil) 857 putmhead(*mp); 858 *mp = m; 859 } 860 if(*cp != nil) 861 cclose(*cp); 862 incref(&m->mount->to->ref); 863 *cp = m->mount->to; 864 runlock(&m->lock); 865 return 1; 866 } 867 runlock(&m->lock); 868 } 869 870 runlock(&pg->ns); 871 return 0; 872 } 873 874 /* 875 * Calls findmount but also updates path. 876 */ 877 static int 878 domount(Chan **cp, Mhead **mp, Path **path) 879 { 880 Chan **lc; 881 Path *p; 882 883 if(findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid) == 0) 884 return 0; 885 886 if(path){ 887 p = *path; 888 p = uniquepath(p); 889 if(p->mlen <= 0) 890 print("domount: path %s has mlen==%d\n", p->s, p->mlen); 891 else{ 892 lc = &p->mtpt[p->mlen-1]; 893 DBG("domount %p %s => add %p (was %p)\n", p, p->s, (*mp)->from, p->mtpt[p->mlen-1]); 894 incref(&(*mp)->from->ref); 895 if(*lc) 896 cclose(*lc); 897 *lc = (*mp)->from; 898 } 899 *path = p; 900 } 901 return 1; 902 } 903 904 /* 905 * If c is the right-hand-side of a mount point, returns the left hand side. 906 * Changes name to reflect the fact that we've uncrossed the mountpoint, 907 * so name had better be ours to change! 908 */ 909 static Chan* 910 undomount(Chan *c, Path *path) 911 { 912 Chan *nc; 913 914 if(path->ref.ref != 1 || path->mlen == 0) 915 print("undomount: path %s ref %ld mlen %d caller %#p\n", 916 path->s, path->ref.ref, path->mlen, getcallerpc(&c)); 917 918 if(path->mlen>0 && (nc=path->mtpt[path->mlen-1]) != nil){ 919 DBG("undomount %p %s => remove %p\n", path, path->s, nc); 920 cclose(c); 921 path->mtpt[path->mlen-1] = nil; 922 c = nc; 923 } 924 return c; 925 } 926 927 /* 928 * Call dev walk but catch errors. 929 */ 930 static Walkqid* 931 ewalk(Chan *c, Chan *nc, char **name, int nname) 932 { 933 Walkqid *wq; 934 935 if(waserror()) 936 return nil; 937 wq = devtab[c->type]->walk(c, nc, name, nname); 938 poperror(); 939 return wq; 940 } 941 942 /* 943 * Either walks all the way or not at all. No partial results in *cp. 944 * *nerror is the number of names to display in an error message. 945 */ 946 static char Edoesnotexist[] = "does not exist"; 947 int 948 walk(Chan **cp, char **names, int nnames, int nomount, int *nerror) 949 { 950 int dev, didmount, dotdot, i, n, nhave, ntry, type; 951 Chan *c, *nc, *mtpt; 952 Path *path; 953 Mhead *mh, *nmh; 954 Mount *f; 955 Walkqid *wq; 956 957 c = *cp; 958 incref(&c->ref); 959 path = c->path; 960 incref(&path->ref); 961 mh = nil; 962 963 /* 964 * While we haven't gotten all the way down the path: 965 * 1. step through a mount point, if any 966 * 2. send a walk request for initial dotdot or initial prefix without dotdot 967 * 3. move to the first mountpoint along the way. 968 * 4. repeat. 969 * 970 * Each time through the loop: 971 * 972 * If didmount==0, c is on the undomount side of the mount point. 973 * If didmount==1, c is on the domount side of the mount point. 974 * Either way, c's full path is path. 975 */ 976 didmount = 0; 977 for(nhave=0; nhave<nnames; nhave+=n){ 978 if((c->qid.type&QTDIR)==0){ 979 if(nerror) 980 *nerror = nhave; 981 pathclose(path); 982 cclose(c); 983 strcpy(up->errstr, Enotdir); 984 if(mh != nil) 985 putmhead(mh); 986 return -1; 987 } 988 ntry = nnames - nhave; 989 if(ntry > MAXWELEM) 990 ntry = MAXWELEM; 991 dotdot = 0; 992 for(i=0; i<ntry; i++){ 993 if(isdotdot(names[nhave+i])){ 994 if(i==0){ 995 dotdot = 1; 996 ntry = 1; 997 }else 998 ntry = i; 999 break; 1000 } 1001 } 1002 1003 if(!dotdot && !nomount && !didmount) 1004 domount(&c, &mh, &path); 1005 1006 type = c->type; 1007 dev = c->dev; 1008 1009 if((wq = ewalk(c, nil, names+nhave, ntry)) == nil){ 1010 /* try a union mount, if any */ 1011 if(mh && !nomount){ 1012 /* 1013 * mh->mount->to == c, so start at mh->mount->next 1014 */ 1015 rlock(&mh->lock); 1016 for(f = mh->mount->next; f; f = f->next) 1017 if((wq = ewalk(f->to, nil, names+nhave, ntry)) != nil) 1018 break; 1019 runlock(&mh->lock); 1020 if(f != nil){ 1021 type = f->to->type; 1022 dev = f->to->dev; 1023 } 1024 } 1025 if(wq == nil){ 1026 cclose(c); 1027 pathclose(path); 1028 if(nerror) 1029 *nerror = nhave+1; 1030 if(mh != nil) 1031 putmhead(mh); 1032 return -1; 1033 } 1034 } 1035 1036 didmount = 0; 1037 if(dotdot){ 1038 assert(wq->nqid == 1); 1039 assert(wq->clone != nil); 1040 1041 path = addelem(path, "..", nil); 1042 nc = undomount(wq->clone, path); 1043 nmh = nil; 1044 n = 1; 1045 }else{ 1046 nc = nil; 1047 nmh = nil; 1048 if(!nomount){ 1049 for(i=0; i<wq->nqid && i<ntry-1; i++){ 1050 if(findmount(&nc, &nmh, type, dev, wq->qid[i])){ 1051 didmount = 1; 1052 break; 1053 } 1054 } 1055 } 1056 if(nc == nil){ /* no mount points along path */ 1057 if(wq->clone == nil){ 1058 cclose(c); 1059 pathclose(path); 1060 if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){ 1061 if(nerror) 1062 *nerror = nhave+wq->nqid+1; 1063 strcpy(up->errstr, Edoesnotexist); 1064 }else{ 1065 if(nerror) 1066 *nerror = nhave+wq->nqid; 1067 strcpy(up->errstr, Enotdir); 1068 } 1069 free(wq); 1070 if(mh != nil) 1071 putmhead(mh); 1072 return -1; 1073 } 1074 n = wq->nqid; 1075 nc = wq->clone; 1076 }else{ /* stopped early, at a mount point */ 1077 didmount = 1; 1078 if(wq->clone != nil){ 1079 cclose(wq->clone); 1080 wq->clone = nil; 1081 } 1082 n = i+1; 1083 } 1084 for(i=0; i<n; i++){ 1085 mtpt = nil; 1086 if(i==n-1 && nmh) 1087 mtpt = nmh->from; 1088 path = addelem(path, names[nhave+i], mtpt); 1089 } 1090 } 1091 cclose(c); 1092 c = nc; 1093 putmhead(mh); 1094 mh = nmh; 1095 free(wq); 1096 } 1097 1098 putmhead(mh); 1099 1100 c = cunique(c); 1101 1102 if(c->umh != nil){ //BUG 1103 print("walk umh\n"); 1104 putmhead(c->umh); 1105 c->umh = nil; 1106 } 1107 1108 pathclose(c->path); 1109 c->path = path; 1110 1111 cclose(*cp); 1112 *cp = c; 1113 if(nerror) 1114 *nerror = nhave; 1115 return 0; 1116 } 1117 1118 /* 1119 * c is a mounted non-creatable directory. find a creatable one. 1120 */ 1121 Chan* 1122 createdir(Chan *c, Mhead *m) 1123 { 1124 Chan *nc; 1125 Mount *f; 1126 1127 rlock(&m->lock); 1128 if(waserror()){ 1129 runlock(&m->lock); 1130 nexterror(); 1131 } 1132 for(f = m->mount; f; f = f->next){ 1133 if(f->mflag&MCREATE){ 1134 nc = cclone(f->to); 1135 runlock(&m->lock); 1136 poperror(); 1137 cclose(c); 1138 return nc; 1139 } 1140 } 1141 error(Enocreate); 1142 return 0; 1143 } 1144 1145 void 1146 saveregisters(void) 1147 { 1148 } 1149 1150 static void 1151 growparse(Elemlist *e) 1152 { 1153 char **new; 1154 int *inew; 1155 enum { Delta = 8 }; 1156 1157 if(e->nelems % Delta == 0){ 1158 new = smalloc((e->nelems+Delta) * sizeof(char*)); 1159 memmove(new, e->elems, e->nelems*sizeof(char*)); 1160 free(e->elems); 1161 e->elems = new; 1162 inew = smalloc((e->nelems+Delta+1) * sizeof(int)); 1163 memmove(inew, e->off, (e->nelems+1)*sizeof(int)); 1164 free(e->off); 1165 e->off = inew; 1166 } 1167 } 1168 1169 /* 1170 * The name is known to be valid. 1171 * Copy the name so slashes can be overwritten. 1172 * An empty string will set nelem=0. 1173 * A path ending in / or /. or /.//./ etc. will have 1174 * e.mustbedir = 1, so that we correctly 1175 * reject, e.g., "/adm/users/." when /adm/users is a file 1176 * rather than a directory. 1177 */ 1178 static void 1179 parsename(char *aname, Elemlist *e) 1180 { 1181 char *name, *slash; 1182 1183 kstrdup(&e->name, aname); 1184 name = e->name; 1185 e->nelems = 0; 1186 e->elems = nil; 1187 e->off = smalloc(sizeof(int)); 1188 e->off[0] = skipslash(name) - name; 1189 for(;;){ 1190 name = skipslash(name); 1191 if(*name == '\0'){ 1192 e->off[e->nelems] = name+strlen(name) - e->name; 1193 e->mustbedir = 1; 1194 break; 1195 } 1196 growparse(e); 1197 e->elems[e->nelems++] = name; 1198 slash = utfrune(name, '/'); 1199 if(slash == nil){ 1200 e->off[e->nelems] = name+strlen(name) - e->name; 1201 e->mustbedir = 0; 1202 break; 1203 } 1204 e->off[e->nelems] = slash - e->name; 1205 *slash++ = '\0'; 1206 name = slash; 1207 } 1208 1209 if(0 && chandebug){ 1210 int i; 1211 1212 print("parsename %s:", e->name); 1213 for(i=0; i<=e->nelems; i++) 1214 print(" %d", e->off[i]); 1215 print("\n"); 1216 } 1217 } 1218 1219 void* 1220 memrchr(void *va, int c, long n) 1221 { 1222 uchar *a, *e; 1223 1224 a = va; 1225 for(e=a+n-1; e>a; e--) 1226 if(*e == c) 1227 return e; 1228 return nil; 1229 } 1230 1231 void 1232 namelenerror(char *aname, int len, char *err) 1233 { 1234 char *ename, *name, *next; 1235 int i, errlen; 1236 1237 /* 1238 * If the name is short enough, just use the whole thing. 1239 */ 1240 errlen = strlen(err); 1241 if(len < ERRMAX/3 || len+errlen < 2*ERRMAX/3) 1242 snprint(up->genbuf, sizeof up->genbuf, "%.*s", 1243 utfnlen(aname, len), aname); 1244 else{ 1245 /* 1246 * Print a suffix of the name, but try to get a little info. 1247 */ 1248 ename = aname+len; 1249 next = ename; 1250 do{ 1251 name = next; 1252 next = memrchr(aname, '/', name-aname); 1253 if(next == nil) 1254 next = aname; 1255 len = ename-next; 1256 }while(len < ERRMAX/3 || len + errlen < 2*ERRMAX/3); 1257 1258 /* 1259 * If the name is ridiculously long, chop it. 1260 */ 1261 if(name == ename){ 1262 name = ename-ERRMAX/4; 1263 if(name <= aname) 1264 panic("bad math in namelenerror"); 1265 /* walk out of current UTF sequence */ 1266 for(i=0; (*name&0xC0)==0x80 && i<3; i++) 1267 name++; 1268 } 1269 snprint(up->genbuf, sizeof up->genbuf, "...%.*s", 1270 utfnlen(name, ename-name), name); 1271 } 1272 snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, err); 1273 nexterror(); 1274 } 1275 1276 void 1277 nameerror(char *name, char *err) 1278 { 1279 namelenerror(name, strlen(name), err); 1280 } 1281 1282 /* 1283 * Turn a name into a channel. 1284 * &name[0] is known to be a valid address. It may be a kernel address. 1285 * 1286 * Opening with amode Aopen, Acreate, Aremove, or Aaccess guarantees 1287 * that the result will be the only reference to that particular fid. 1288 * This is necessary since we might pass the result to 1289 * devtab[]->remove(). 1290 * 1291 * Opening Atodir or Amount does not guarantee this. 1292 * 1293 * Under certain circumstances, opening Aaccess will cause 1294 * an unnecessary clone in order to get a cunique Chan so it 1295 * can attach the correct name. Sysstat and sys_stat need the 1296 * correct name so they can rewrite the stat info. 1297 */ 1298 Chan* 1299 namec(char *aname, int amode, int omode, ulong perm) 1300 { 1301 int len, n, t, nomount; 1302 Chan *c, *cnew; 1303 Path *path; 1304 Elemlist e; 1305 Rune r; 1306 Mhead *m; 1307 char *createerr, tmperrbuf[ERRMAX]; 1308 char *name; 1309 1310 if(aname[0] == '\0') 1311 error("empty file name"); 1312 aname = validnamedup(aname, 1); 1313 if(waserror()){ 1314 free(aname); 1315 nexterror(); 1316 } 1317 if(tracesyscalls) 1318 iprint("\tnamec %s\n", aname); 1319 DBG("namec %s %d %d\n", aname, amode, omode); 1320 name = aname; 1321 1322 /* 1323 * Find the starting off point (the current slash, the root of 1324 * a device tree, or the current dot) as well as the name to 1325 * evaluate starting there. 1326 */ 1327 nomount = 0; 1328 switch(name[0]){ 1329 case '/': 1330 c = up->slash; 1331 incref(&c->ref); 1332 break; 1333 1334 case '#': 1335 nomount = 1; 1336 up->genbuf[0] = '\0'; 1337 n = 0; 1338 while(*name != '\0' && (*name != '/' || n < 2)){ 1339 if(n >= sizeof(up->genbuf)-1) 1340 error(Efilename); 1341 up->genbuf[n++] = *name++; 1342 } 1343 up->genbuf[n] = '\0'; 1344 /* 1345 * noattach is sandboxing. 1346 * 1347 * the OK exceptions are: 1348 * | it only gives access to pipes you create 1349 * d this process's file descriptors 1350 * e this process's environment 1351 * the iffy exceptions are: 1352 * c time and pid, but also cons and consctl 1353 * p control of your own processes (and unfortunately 1354 * any others left unprotected) 1355 */ 1356 n = chartorune(&r, up->genbuf+1)+1; 1357 /* actually / is caught by parsing earlier */ 1358 if(utfrune("M", r)) 1359 error(Enoattach); 1360 if(up->pgrp->noattach && utfrune("|decp", r)==nil) 1361 error(Enoattach); 1362 t = devno(r, 1); 1363 if(t == -1) 1364 error(Ebadsharp); 1365 c = devtab[t]->attach(up->genbuf+n); 1366 break; 1367 1368 default: 1369 c = up->dot; 1370 incref(&c->ref); 1371 break; 1372 } 1373 1374 e.aname = aname; 1375 e.prefix = name - aname; 1376 e.name = nil; 1377 e.elems = nil; 1378 e.off = nil; 1379 e.nelems = 0; 1380 e.nerror = 0; 1381 if(waserror()){ 1382 cclose(c); 1383 free(e.name); 1384 free(e.elems); 1385 /* 1386 * Prepare nice error, showing first e.nerror elements of name. 1387 */ 1388 if(e.nerror == 0) 1389 nexterror(); 1390 strcpy(tmperrbuf, up->errstr); 1391 if(e.off[e.nerror]==0) 1392 print("nerror=%d but off=%d\n", 1393 e.nerror, e.off[e.nerror]); 1394 if(0 && chandebug) 1395 print("showing %d+%d/%d (of %d) of %s (%d %d)\n", e.prefix, e.off[e.nerror], e.nerror, e.nelems, aname, e.off[0], e.off[1]); 1396 len = e.prefix+e.off[e.nerror]; 1397 free(e.off); 1398 namelenerror(aname, len, tmperrbuf); 1399 } 1400 1401 /* 1402 * Build a list of elements in the name. 1403 */ 1404 parsename(name, &e); 1405 1406 /* 1407 * On create, .... 1408 */ 1409 if(amode == Acreate){ 1410 /* perm must have DMDIR if last element is / or /. */ 1411 if(e.mustbedir && !(perm&DMDIR)){ 1412 e.nerror = e.nelems; 1413 error("create without DMDIR"); 1414 } 1415 1416 /* don't try to walk the last path element just yet. */ 1417 if(e.nelems == 0) 1418 error(Eexist); 1419 e.nelems--; 1420 } 1421 1422 if(walk(&c, e.elems, e.nelems, nomount, &e.nerror) < 0){ 1423 if(e.nerror < 0 || e.nerror > e.nelems){ 1424 print("namec %s walk error nerror=%d\n", aname, e.nerror); 1425 e.nerror = 0; 1426 } 1427 nexterror(); 1428 } 1429 1430 if(e.mustbedir && !(c->qid.type&QTDIR)) 1431 error("not a directory"); 1432 1433 if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR)) 1434 error("cannot exec directory"); 1435 1436 switch(amode){ 1437 case Abind: 1438 /* no need to maintain path - cannot dotdot an Abind */ 1439 m = nil; 1440 if(!nomount) 1441 domount(&c, &m, nil); 1442 if(c->umh != nil) 1443 putmhead(c->umh); 1444 c->umh = m; 1445 break; 1446 1447 case Aaccess: 1448 case Aremove: 1449 case Aopen: 1450 Open: 1451 /* save&update the name; domount might change c */ 1452 path = c->path; 1453 incref(&path->ref); 1454 m = nil; 1455 if(!nomount) 1456 domount(&c, &m, &path); 1457 1458 /* our own copy to open or remove */ 1459 c = cunique(c); 1460 1461 /* now it's our copy anyway, we can put the name back */ 1462 pathclose(c->path); 1463 c->path = path; 1464 1465 /* record whether c is on a mount point */ 1466 c->ismtpt = m!=nil; 1467 1468 switch(amode){ 1469 case Aaccess: 1470 case Aremove: 1471 putmhead(m); 1472 break; 1473 1474 case Aopen: 1475 case Acreate: 1476 if(c->umh != nil){ 1477 print("cunique umh Open\n"); 1478 putmhead(c->umh); 1479 c->umh = nil; 1480 } 1481 /* only save the mount head if it's a multiple element union */ 1482 if(m && m->mount && m->mount->next) 1483 c->umh = m; 1484 else 1485 putmhead(m); 1486 1487 /* save registers else error() in open has wrong value of c saved */ 1488 saveregisters(); 1489 1490 if(omode == OEXEC) 1491 c->flag &= ~CCACHE; 1492 1493 c = devtab[c->type]->open(c, omode&~OCEXEC); 1494 1495 if(omode & OCEXEC) 1496 c->flag |= CCEXEC; 1497 if(omode & ORCLOSE) 1498 c->flag |= CRCLOSE; 1499 break; 1500 } 1501 break; 1502 1503 case Atodir: 1504 /* 1505 * Directories (e.g. for cd) are left before the mount point, 1506 * so one may mount on / or . and see the effect. 1507 */ 1508 if(!(c->qid.type & QTDIR)) 1509 error(Enotdir); 1510 break; 1511 1512 case Amount: 1513 /* 1514 * When mounting on an already mounted upon directory, 1515 * one wants subsequent mounts to be attached to the 1516 * original directory, not the replacement. Don't domount. 1517 */ 1518 break; 1519 1520 case Acreate: 1521 /* 1522 * We've already walked all but the last element. 1523 * If the last exists, try to open it OTRUNC. 1524 * If omode&OEXCL is set, just give up. 1525 */ 1526 e.nelems++; 1527 e.nerror++; 1528 if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){ 1529 if(omode&OEXCL) 1530 error(Eexist); 1531 omode |= OTRUNC; 1532 goto Open; 1533 } 1534 1535 /* 1536 * The semantics of the create(2) system call are that if the 1537 * file exists and can be written, it is to be opened with truncation. 1538 * On the other hand, the create(5) message fails if the file exists. 1539 * If we get two create(2) calls happening simultaneously, 1540 * they might both get here and send create(5) messages, but only 1541 * one of the messages will succeed. To provide the expected create(2) 1542 * semantics, the call with the failed message needs to try the above 1543 * walk again, opening for truncation. This correctly solves the 1544 * create/create race, in the sense that any observable outcome can 1545 * be explained as one happening before the other. 1546 * The create/create race is quite common. For example, it happens 1547 * when two rc subshells simultaneously update the same 1548 * environment variable. 1549 * 1550 * The implementation still admits a create/create/remove race: 1551 * (A) walk to file, fails 1552 * (B) walk to file, fails 1553 * (A) create file, succeeds, returns 1554 * (B) create file, fails 1555 * (A) remove file, succeeds, returns 1556 * (B) walk to file, return failure. 1557 * 1558 * This is hardly as common as the create/create race, and is really 1559 * not too much worse than what might happen if (B) got a hold of a 1560 * file descriptor and then the file was removed -- either way (B) can't do 1561 * anything with the result of the create call. So we don't care about this race. 1562 * 1563 * Applications that care about more fine-grained decision of the races 1564 * can use the OEXCL flag to get at the underlying create(5) semantics; 1565 * by default we provide the common case. 1566 * 1567 * We need to stay behind the mount point in case we 1568 * need to do the first walk again (should the create fail). 1569 * 1570 * We also need to cross the mount point and find the directory 1571 * in the union in which we should be creating. 1572 * 1573 * The channel staying behind is c, the one moving forward is cnew. 1574 */ 1575 m = nil; 1576 cnew = nil; /* is this assignment necessary? */ 1577 if(!waserror()){ /* try create */ 1578 if(!nomount && findmount(&cnew, &m, c->type, c->dev, c->qid)) 1579 cnew = createdir(cnew, m); 1580 else{ 1581 cnew = c; 1582 incref(&cnew->ref); 1583 } 1584 1585 /* 1586 * We need our own copy of the Chan because we're 1587 * about to send a create, which will move it. Once we have 1588 * our own copy, we can fix the name, which might be wrong 1589 * if findmount gave us a new Chan. 1590 */ 1591 cnew = cunique(cnew); 1592 pathclose(cnew->path); 1593 cnew->path = c->path; 1594 incref(&cnew->path->ref); 1595 1596 devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm); 1597 poperror(); 1598 if(omode & OCEXEC) 1599 cnew->flag |= CCEXEC; 1600 if(omode & ORCLOSE) 1601 cnew->flag |= CRCLOSE; 1602 if(m) 1603 putmhead(m); 1604 cclose(c); 1605 c = cnew; 1606 c->path = addelem(c->path, e.elems[e.nelems-1], nil); 1607 break; 1608 } 1609 1610 /* create failed */ 1611 cclose(cnew); 1612 if(m) 1613 putmhead(m); 1614 if(omode & OEXCL) 1615 nexterror(); 1616 /* save error */ 1617 createerr = up->errstr; 1618 up->errstr = tmperrbuf; 1619 /* note: we depend that walk does not error */ 1620 if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){ 1621 up->errstr = createerr; 1622 error(createerr); /* report true error */ 1623 } 1624 up->errstr = createerr; 1625 omode |= OTRUNC; 1626 goto Open; 1627 1628 default: 1629 panic("unknown namec access %d\n", amode); 1630 } 1631 1632 /* place final element in genbuf for e.g. exec */ 1633 if(e.nelems > 0) 1634 kstrcpy(up->genbuf, e.elems[e.nelems-1], sizeof up->genbuf); 1635 else 1636 kstrcpy(up->genbuf, ".", sizeof up->genbuf); 1637 free(e.name); 1638 free(e.elems); 1639 free(e.off); 1640 poperror(); /* e c */ 1641 free(aname); 1642 poperror(); /* aname */ 1643 1644 return c; 1645 } 1646 1647 /* 1648 * name is valid. skip leading / and ./ as much as possible 1649 */ 1650 char* 1651 skipslash(char *name) 1652 { 1653 while(name[0]=='/' || (name[0]=='.' && (name[1]==0 || name[1]=='/'))) 1654 name++; 1655 return name; 1656 } 1657 1658 char isfrog[256]={ 1659 /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, 1660 /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, 1661 /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, 1662 /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, 1663 ['/'] 1, 1664 [0x7f] 1, 1665 }; 1666 1667 /* 1668 * Check that the name 1669 * a) is in valid memory. 1670 * b) is shorter than 2^16 bytes, so it can fit in a 9P string field. 1671 * c) contains no frogs. 1672 * The first byte is known to be addressible by the requester, so the 1673 * routine works for kernel and user memory both. 1674 * The parameter slashok flags whether a slash character is an error 1675 * or a valid character. 1676 * 1677 * The parameter dup flags whether the string should be copied 1678 * out of user space before being scanned the second time. 1679 * (Otherwise a malicious thread could remove the NUL, causing us 1680 * to access unchecked addresses.) 1681 */ 1682 static char* 1683 validname0(char *aname, int slashok, int dup, ulong pc) 1684 { 1685 char *ename, *name, *s; 1686 int c, n; 1687 Rune r; 1688 1689 name = aname; 1690 if(isuaddr(name)){ 1691 if(!dup) 1692 print("warning: validname called from %lux with user pointer", pc); 1693 char *p; 1694 uint t; 1695 p = name; 1696 t = BY2PG-((ulong)p&(BY2PG-1)); 1697 while((ename=vmemchr(p, 0, t)) == nil){ 1698 p += t; 1699 t = BY2PG; 1700 } 1701 }else 1702 ename = memchr(name, 0, (1<<16)); 1703 1704 if(ename==nil || ename-name>=(1<<16)) 1705 error("name too long"); 1706 1707 s = nil; 1708 if(dup){ 1709 n = ename-name; 1710 s = smalloc(n+1); 1711 memmove(s, name, n); 1712 s[n] = 0; 1713 aname = s; 1714 name = s; 1715 setmalloctag(s, pc); 1716 } 1717 1718 while(*name){ 1719 /* all characters above '~' are ok */ 1720 c = *(uchar*)name; 1721 if(c >= Runeself) 1722 name += chartorune(&r, name); 1723 else{ 1724 if(isfrog[c]) 1725 if(!slashok || c!='/'){ 1726 snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname); 1727 free(s); 1728 error(up->genbuf); 1729 } 1730 name++; 1731 } 1732 } 1733 return s; 1734 } 1735 1736 void 1737 validname(char *aname, int slashok) 1738 { 1739 validname0(aname, slashok, 0, getcallerpc(&aname)); 1740 } 1741 1742 char* 1743 validnamedup(char *aname, int slashok) 1744 { 1745 return validname0(aname, slashok, 1, getcallerpc(&aname)); 1746 } 1747 1748 void 1749 isdir(Chan *c) 1750 { 1751 if(c->qid.type & QTDIR) 1752 return; 1753 error(Enotdir); 1754 } 1755 1756 /* 1757 * This is necessary because there are many 1758 * pointers to the top of a given mount list: 1759 * 1760 * - the mhead in the namespace hash table 1761 * - the mhead in chans returned from findmount: 1762 * used in namec and then by unionread. 1763 * - the mhead in chans returned from createdir: 1764 * used in the open/create race protect, which is gone. 1765 * 1766 * The RWlock in the Mhead protects the mount list it contains. 1767 * The mount list is deleted when we cunmount. 1768 * The RWlock ensures that nothing is using the mount list at that time. 1769 * 1770 * It is okay to replace c->mh with whatever you want as 1771 * long as you are sure you have a unique reference to it. 1772 * 1773 * This comment might belong somewhere else. 1774 */ 1775 void 1776 putmhead(Mhead *m) 1777 { 1778 if(m && decref(&m->ref) == 0){ 1779 m->mount = (Mount*)0xCafeBeef; 1780 free(m); 1781 } 1782 } 1783