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