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