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