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