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