The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/port/chan.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 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;
   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);
  102         x = ++r->ref;
  103         unlock(r);
  104         return x;
  105 }
  106 
  107 long
  108 decref(Ref *r)
  109 {
  110         long x;
  111 
  112         lock(r);
  113         x = --r->ref;
  114         unlock(r);
  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         static Lock l;
  172 
  173         n = strlen(s)+1;
  174         /* if it's a user, we can wait for memory; if not, something's very wrong */
  175         if(up){
  176                 t = smalloc(n);
  177                 setmalloctag(t, getcallerpc(&p));
  178         }else{
  179                 t = malloc(n);
  180                 if(t == nil)
  181                         panic("kstrdup: no memory");
  182         }
  183         memmove(t, s, n);
  184         prev = *p;
  185         *p = t;
  186         free(prev);
  187 }
  188 
  189 void
  190 chandevreset(void)
  191 {
  192         int i;
  193 
  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);
  225         c = chanalloc.free;
  226         if(c != 0)
  227                 chanalloc.free = c->next;
  228         unlock(&chanalloc);
  229 
  230         if(c == nil){
  231                 c = smalloc(sizeof(Chan));
  232                 lock(&chanalloc);
  233                 c->fid = ++chanalloc.fid;
  234                 c->link = chanalloc.list;
  235                 chanalloc.list = c;
  236                 unlock(&chanalloc);
  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 = 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 = 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 = 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]);
  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);
  330         for(i=0; i<p->mlen; i++)
  331                 DBG(" %p", p->mtpt[i]);
  332         DBG("\n");
  333 
  334         if(decref(p))
  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 > 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);
  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);
  467         c->next = chanalloc.free;
  468         chanalloc.free = c;
  469         unlock(&chanalloc);
  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);
  479         if(decref(c))
  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);
  510 
  511         if(decref(c))
  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*)
  530 {
  531         return clunkq.head != nil;
  532 }
  533 
  534 void
  535 closeproc(void*)
  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 != 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 = 1;
  623         mh->from = from;
  624         incref(from);
  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);
  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);
  856                                 if(*mp != nil)
  857                                         putmhead(*mp);
  858                                 *mp = m;
  859                         }
  860                         if(*cp != nil)
  861                                 cclose(*cp);
  862                         incref(m->mount->to);
  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);
  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 != 1 || path->mlen == 0)
  915                 print("undomount: path %s ref %ld mlen %d caller %#p\n",
  916                         path->s, path->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);
  959         path = c->path;
  960         incref(path);
  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         DBG("namec %s %d %d\n", aname, amode, omode);
 1318         name = aname;
 1319 
 1320         /*
 1321          * Find the starting off point (the current slash, the root of
 1322          * a device tree, or the current dot) as well as the name to
 1323          * evaluate starting there.
 1324          */
 1325         nomount = 0;
 1326         switch(name[0]){
 1327         case '/':
 1328                 c = up->slash;
 1329                 incref(c);
 1330                 break;
 1331         
 1332         case '#':
 1333                 nomount = 1;
 1334                 up->genbuf[0] = '\0';
 1335                 n = 0;
 1336                 while(*name != '\0' && (*name != '/' || n < 2)){
 1337                         if(n >= sizeof(up->genbuf)-1)
 1338                                 error(Efilename);
 1339                         up->genbuf[n++] = *name++;
 1340                 }
 1341                 up->genbuf[n] = '\0';
 1342                 /*
 1343                  *  noattach is sandboxing.
 1344                  *
 1345                  *  the OK exceptions are:
 1346                  *      |  it only gives access to pipes you create
 1347                  *      d  this process's file descriptors
 1348                  *      e  this process's environment
 1349                  *  the iffy exceptions are:
 1350                  *      c  time and pid, but also cons and consctl
 1351                  *      p  control of your own processes (and unfortunately
 1352                  *         any others left unprotected)
 1353                  */
 1354                 n = chartorune(&r, up->genbuf+1)+1;
 1355                 /* actually / is caught by parsing earlier */
 1356                 if(utfrune("M", r))
 1357                         error(Enoattach);
 1358                 if(up->pgrp->noattach && utfrune("|decp", r)==nil)
 1359                         error(Enoattach);
 1360                 t = devno(r, 1);
 1361                 if(t == -1)
 1362                         error(Ebadsharp);
 1363                 c = devtab[t]->attach(up->genbuf+n);
 1364                 break;
 1365 
 1366         default:
 1367                 c = up->dot;
 1368                 incref(c);
 1369                 break;
 1370         }
 1371 
 1372         e.aname = aname;
 1373         e.prefix = name - aname;
 1374         e.name = nil;
 1375         e.elems = nil;
 1376         e.off = nil;
 1377         e.nelems = 0;
 1378         e.nerror = 0;
 1379         if(waserror()){
 1380                 cclose(c);
 1381                 free(e.name);
 1382                 free(e.elems);
 1383                 /*
 1384                  * Prepare nice error, showing first e.nerror elements of name.
 1385                  */
 1386                 if(e.nerror == 0)
 1387                         nexterror();
 1388                 strcpy(tmperrbuf, up->errstr);
 1389                 if(e.off[e.nerror]==0)
 1390                         print("nerror=%d but off=%d\n",
 1391                                 e.nerror, e.off[e.nerror]);
 1392                 if(0 && chandebug)
 1393                         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]);
 1394                 len = e.prefix+e.off[e.nerror];
 1395                 free(e.off);
 1396                 namelenerror(aname, len, tmperrbuf);
 1397         }
 1398 
 1399         /*
 1400          * Build a list of elements in the name.
 1401          */
 1402         parsename(name, &e);
 1403 
 1404         /*
 1405          * On create, ....
 1406          */
 1407         if(amode == Acreate){
 1408                 /* perm must have DMDIR if last element is / or /. */
 1409                 if(e.mustbedir && !(perm&DMDIR)){
 1410                         e.nerror = e.nelems;
 1411                         error("create without DMDIR");
 1412                 }
 1413 
 1414                 /* don't try to walk the last path element just yet. */
 1415                 if(e.nelems == 0)
 1416                         error(Eexist);
 1417                 e.nelems--;
 1418         }
 1419 
 1420         if(walk(&c, e.elems, e.nelems, nomount, &e.nerror) < 0){
 1421                 if(e.nerror < 0 || e.nerror > e.nelems){
 1422                         print("namec %s walk error nerror=%d\n", aname, e.nerror);
 1423                         e.nerror = 0;
 1424                 }
 1425                 nexterror();
 1426         }
 1427 
 1428         if(e.mustbedir && !(c->qid.type&QTDIR))
 1429                 error("not a directory");
 1430 
 1431         if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR))
 1432                 error("cannot exec directory");
 1433 
 1434         switch(amode){
 1435         case Abind:
 1436                 /* no need to maintain path - cannot dotdot an Abind */
 1437                 m = nil;
 1438                 if(!nomount)
 1439                         domount(&c, &m, nil);
 1440                 if(c->umh != nil)
 1441                         putmhead(c->umh);
 1442                 c->umh = m;
 1443                 break;
 1444 
 1445         case Aaccess:
 1446         case Aremove:
 1447         case Aopen:
 1448         Open:
 1449                 /* save&update the name; domount might change c */
 1450                 path = c->path;
 1451                 incref(path);
 1452                 m = nil;
 1453                 if(!nomount)
 1454                         domount(&c, &m, &path);
 1455 
 1456                 /* our own copy to open or remove */
 1457                 c = cunique(c);
 1458 
 1459                 /* now it's our copy anyway, we can put the name back */
 1460                 pathclose(c->path);
 1461                 c->path = path;
 1462 
 1463                 /* record whether c is on a mount point */
 1464                 c->ismtpt = m!=nil;
 1465 
 1466                 switch(amode){
 1467                 case Aaccess:
 1468                 case Aremove:
 1469                         putmhead(m);
 1470                         break;
 1471 
 1472                 case Aopen:
 1473                 case Acreate:
 1474 if(c->umh != nil){
 1475         print("cunique umh Open\n");
 1476         putmhead(c->umh);
 1477         c->umh = nil;
 1478 }
 1479                         /* only save the mount head if it's a multiple element union */
 1480                         if(m && m->mount && m->mount->next)
 1481                                 c->umh = m;
 1482                         else
 1483                                 putmhead(m);
 1484 
 1485                         /* save registers else error() in open has wrong value of c saved */
 1486                         saveregisters();
 1487 
 1488                         if(omode == OEXEC)
 1489                                 c->flag &= ~CCACHE;
 1490 
 1491                         c = devtab[c->type]->open(c, omode&~OCEXEC);
 1492 
 1493                         if(omode & OCEXEC)
 1494                                 c->flag |= CCEXEC;
 1495                         if(omode & ORCLOSE)
 1496                                 c->flag |= CRCLOSE;
 1497                         break;
 1498                 }
 1499                 break;
 1500 
 1501         case Atodir:
 1502                 /*
 1503                  * Directories (e.g. for cd) are left before the mount point,
 1504                  * so one may mount on / or . and see the effect.
 1505                  */
 1506                 if(!(c->qid.type & QTDIR))
 1507                         error(Enotdir);
 1508                 break;
 1509 
 1510         case Amount:
 1511                 /*
 1512                  * When mounting on an already mounted upon directory,
 1513                  * one wants subsequent mounts to be attached to the
 1514                  * original directory, not the replacement.  Don't domount.
 1515                  */
 1516                 break;
 1517 
 1518         case Acreate:
 1519                 /*
 1520                  * We've already walked all but the last element.
 1521                  * If the last exists, try to open it OTRUNC.
 1522                  * If omode&OEXCL is set, just give up.
 1523                  */
 1524                 e.nelems++;
 1525                 e.nerror++;
 1526                 if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
 1527                         if(omode&OEXCL)
 1528                                 error(Eexist);
 1529                         omode |= OTRUNC;
 1530                         goto Open;
 1531                 }
 1532 
 1533                 /*
 1534                  * The semantics of the create(2) system call are that if the
 1535                  * file exists and can be written, it is to be opened with truncation.
 1536                  * On the other hand, the create(5) message fails if the file exists.
 1537                  * If we get two create(2) calls happening simultaneously, 
 1538                  * they might both get here and send create(5) messages, but only 
 1539                  * one of the messages will succeed.  To provide the expected create(2)
 1540                  * semantics, the call with the failed message needs to try the above
 1541                  * walk again, opening for truncation.  This correctly solves the 
 1542                  * create/create race, in the sense that any observable outcome can
 1543                  * be explained as one happening before the other.
 1544                  * The create/create race is quite common.  For example, it happens
 1545                  * when two rc subshells simultaneously update the same
 1546                  * environment variable.
 1547                  *
 1548                  * The implementation still admits a create/create/remove race:
 1549                  * (A) walk to file, fails
 1550                  * (B) walk to file, fails
 1551                  * (A) create file, succeeds, returns 
 1552                  * (B) create file, fails
 1553                  * (A) remove file, succeeds, returns
 1554                  * (B) walk to file, return failure.
 1555                  *
 1556                  * This is hardly as common as the create/create race, and is really
 1557                  * not too much worse than what might happen if (B) got a hold of a
 1558                  * file descriptor and then the file was removed -- either way (B) can't do
 1559                  * anything with the result of the create call.  So we don't care about this race.
 1560                  *
 1561                  * Applications that care about more fine-grained decision of the races
 1562                  * can use the OEXCL flag to get at the underlying create(5) semantics;
 1563                  * by default we provide the common case.
 1564                  *
 1565                  * We need to stay behind the mount point in case we
 1566                  * need to do the first walk again (should the create fail).
 1567                  *
 1568                  * We also need to cross the mount point and find the directory
 1569                  * in the union in which we should be creating.
 1570                  *
 1571                  * The channel staying behind is c, the one moving forward is cnew.
 1572                  */
 1573                 m = nil;
 1574                 cnew = nil;     /* is this assignment necessary? */
 1575                 if(!waserror()){        /* try create */
 1576                         if(!nomount && findmount(&cnew, &m, c->type, c->dev, c->qid))
 1577                                 cnew = createdir(cnew, m);
 1578                         else{
 1579                                 cnew = c;
 1580                                 incref(cnew);
 1581                         }
 1582 
 1583                         /*
 1584                          * We need our own copy of the Chan because we're
 1585                          * about to send a create, which will move it.  Once we have
 1586                          * our own copy, we can fix the name, which might be wrong
 1587                          * if findmount gave us a new Chan.
 1588                          */
 1589                         cnew = cunique(cnew);
 1590                         pathclose(cnew->path);
 1591                         cnew->path = c->path;
 1592                         incref(cnew->path);
 1593 
 1594                         devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm);
 1595                         poperror();
 1596                         if(omode & OCEXEC)
 1597                                 cnew->flag |= CCEXEC;
 1598                         if(omode & ORCLOSE)
 1599                                 cnew->flag |= CRCLOSE;
 1600                         if(m)
 1601                                 putmhead(m);
 1602                         cclose(c);
 1603                         c = cnew;
 1604                         c->path = addelem(c->path, e.elems[e.nelems-1], nil);
 1605                         break;
 1606                 }
 1607 
 1608                 /* create failed */
 1609                 cclose(cnew);
 1610                 if(m)
 1611                         putmhead(m);
 1612                 if(omode & OEXCL)
 1613                         nexterror();
 1614                 /* save error */
 1615                 createerr = up->errstr;
 1616                 up->errstr = tmperrbuf;
 1617                 /* note: we depend that walk does not error */
 1618                 if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
 1619                         up->errstr = createerr;
 1620                         error(createerr);       /* report true error */
 1621                 }
 1622                 up->errstr = createerr;
 1623                 omode |= OTRUNC;
 1624                 goto Open;
 1625 
 1626         default:
 1627                 panic("unknown namec access %d\n", amode);
 1628         }
 1629 
 1630         /* place final element in genbuf for e.g. exec */
 1631         if(e.nelems > 0)
 1632                 kstrcpy(up->genbuf, e.elems[e.nelems-1], sizeof up->genbuf);
 1633         else
 1634                 kstrcpy(up->genbuf, ".", sizeof up->genbuf);
 1635         free(e.name);
 1636         free(e.elems);
 1637         free(e.off);
 1638         poperror();     /* e c */
 1639         free(aname);
 1640         poperror();     /* aname */
 1641 
 1642         return c;
 1643 }
 1644 
 1645 /*
 1646  * name is valid. skip leading / and ./ as much as possible
 1647  */
 1648 char*
 1649 skipslash(char *name)
 1650 {
 1651         while(name[0]=='/' || (name[0]=='.' && (name[1]==0 || name[1]=='/')))
 1652                 name++;
 1653         return name;
 1654 }
 1655 
 1656 char isfrog[256]={
 1657         /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1,
 1658         /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1,
 1659         /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1,
 1660         /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1,
 1661         ['/']   1,
 1662         [0x7f]  1,
 1663 };
 1664 
 1665 /*
 1666  * Check that the name
 1667  *  a) is in valid memory.
 1668  *  b) is shorter than 2^16 bytes, so it can fit in a 9P string field.
 1669  *  c) contains no frogs.
 1670  * The first byte is known to be addressible by the requester, so the
 1671  * routine works for kernel and user memory both.
 1672  * The parameter slashok flags whether a slash character is an error
 1673  * or a valid character.
 1674  *
 1675  * The parameter dup flags whether the string should be copied
 1676  * out of user space before being scanned the second time.
 1677  * (Otherwise a malicious thread could remove the NUL, causing us
 1678  * to access unchecked addresses.) 
 1679  */
 1680 static char*
 1681 validname0(char *aname, int slashok, int dup, ulong pc)
 1682 {
 1683         char *p, *ename, *name, *s;
 1684         uint t;
 1685         int c, n;
 1686         Rune r;
 1687 
 1688         name = aname;
 1689         if((ulong)name < KZERO){
 1690                 validaddr((ulong)name, 1, 0);
 1691                 if(!dup)
 1692                         print("warning: validname called from %lux with user pointer", pc);
 1693                 p = name;
 1694                 t = BY2PG-((ulong)p&(BY2PG-1));
 1695                 while((ename=vmemchr(p, 0, t)) == nil){
 1696                         p += t;
 1697                         t = BY2PG;
 1698                 }
 1699         }else
 1700                 ename = memchr(name, 0, (1<<16));
 1701 
 1702         if(ename==nil || ename-name>=(1<<16))
 1703                 error("name too long");
 1704 
 1705         s = nil;
 1706         if(dup){
 1707                 n = ename-name;
 1708                 s = smalloc(n+1);
 1709                 memmove(s, name, n);
 1710                 s[n] = 0;
 1711                 aname = s;
 1712                 name = s;
 1713                 setmalloctag(s, pc);
 1714         }
 1715         
 1716         while(*name){
 1717                 /* all characters above '~' are ok */
 1718                 c = *(uchar*)name;
 1719                 if(c >= Runeself)
 1720                         name += chartorune(&r, name);
 1721                 else{
 1722                         if(isfrog[c])
 1723                                 if(!slashok || c!='/'){
 1724                                         snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname);
 1725                                         free(s);
 1726                                         error(up->genbuf);
 1727                         }
 1728                         name++;
 1729                 }
 1730         }
 1731         return s;
 1732 }
 1733 
 1734 void
 1735 validname(char *aname, int slashok)
 1736 {
 1737         validname0(aname, slashok, 0, getcallerpc(&aname));
 1738 }
 1739 
 1740 char*
 1741 validnamedup(char *aname, int slashok)
 1742 {
 1743         return validname0(aname, slashok, 1, getcallerpc(&aname));
 1744 }
 1745 
 1746 void
 1747 isdir(Chan *c)
 1748 {
 1749         if(c->qid.type & QTDIR)
 1750                 return;
 1751         error(Enotdir);
 1752 }
 1753 
 1754 /*
 1755  * This is necessary because there are many
 1756  * pointers to the top of a given mount list:
 1757  *
 1758  *      - the mhead in the namespace hash table
 1759  *      - the mhead in chans returned from findmount:
 1760  *        used in namec and then by unionread.
 1761  *      - the mhead in chans returned from createdir:
 1762  *        used in the open/create race protect, which is gone.
 1763  *
 1764  * The RWlock in the Mhead protects the mount list it contains.
 1765  * The mount list is deleted when we cunmount.
 1766  * The RWlock ensures that nothing is using the mount list at that time.
 1767  *
 1768  * It is okay to replace c->mh with whatever you want as 
 1769  * long as you are sure you have a unique reference to it.
 1770  *
 1771  * This comment might belong somewhere else.
 1772  */
 1773 void
 1774 putmhead(Mhead *m)
 1775 {
 1776         if(m && decref(m) == 0){
 1777                 m->mount = (Mount*)0xCafeBeef;
 1778                 free(m);
 1779         }
 1780 }
 1781 

Cache object: 9b2b35912db796686040c820abc27c10


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.