|
|
1.1 root 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: struct
9: {
10: Lock;
11: Chan *free;
12: int fid;
13: }chanalloc;
14:
15: int
16: incref(Ref *r)
17: {
18: int x;
19:
20: lock(r);
21: x = ++r->ref;
22: unlock(r);
23: return x;
24: }
25:
26: int
27: decref(Ref *r)
28: {
29: int x;
30:
31: lock(r);
32: x = --r->ref;
33: unlock(r);
34: if(x < 0)
35: panic("decref");
36:
37: return x;
38: }
39:
40: void
41: chandevreset(void)
42: {
43: int i;
44:
45: for(i=0; devchar[i]; i++)
46: (*devtab[i].reset)();
47: }
48:
49: void
50: chandevinit(void)
51: {
52: int i;
53:
54: for(i=0; devchar[i]; i++)
55: (*devtab[i].init)();
56: }
57:
58: Chan*
59: newchan(void)
60: {
61: Chan *c;
62: int nfid;
63:
64: SET(nfid);
65:
66: lock(&chanalloc);
67: c = chanalloc.free;
68: if(c)
69: chanalloc.free = c->next;
70: else{
71: nfid = ++chanalloc.fid;
72: if(nfid > 50000)
73: panic("too many channels");
74: }
75: unlock(&chanalloc);
76:
77: if(c == 0) {
78: c = smalloc(sizeof(Chan));
79: c->fid = nfid;
80: }
81:
82: /* if you get an error before associating with a dev,
83: close calls rootclose, a nop */
84: c->type = 0;
85: c->flag = 0;
86: c->ref = 1;
87: c->dev = 0;
88: c->offset = 0;
89: c->mnt = 0;
90: c->stream = 0;
91: c->aux = 0;
92: c->mchan = 0;
93: c->mqid = (Qid){0, 0};
94: return c;
95: }
96:
97: void
98: chanfree(Chan *c)
99: {
100: c->flag = CFREE;
101: if(c->session){
102: freesession(c->session);
103: c->session = 0;
104: }
105: lock(&chanalloc);
106: c->next = chanalloc.free;
107: chanalloc.free = c;
108: unlock(&chanalloc);
109: }
110:
111: void
112: close(Chan *c)
113: {
114: if(c->flag & CFREE)
115: panic("close");
116:
117: if(decref(c) == 0){
118: if(!waserror()) {
119: (*devtab[c->type].close)(c);
120: poperror();
121: }
122: chanfree(c);
123: }
124: }
125:
126: int
127: eqqid(Qid a, Qid b)
128: {
129: return a.path==b.path && a.vers==b.vers;
130: }
131:
132: int
133: eqchan(Chan *a, Chan *b, int pathonly)
134: {
135: if(a->qid.path != b->qid.path)
136: return 0;
137: if(!pathonly && a->qid.vers!=b->qid.vers)
138: return 0;
139: if(a->type != b->type)
140: return 0;
141: if(a->dev != b->dev)
142: return 0;
143: return 1;
144: }
145:
146: int
147: mount(Chan *new, Chan *old, int flag)
148: {
149: Pgrp *pg;
150: Mount *nm, *f;
151: Mhead *m, **l;
152: int order;
153:
154: if(CHDIR & (old->qid.path^new->qid.path))
155: error(Emount);
156:
157: order = flag&MORDER;
158:
159: if((old->qid.path&CHDIR)==0 && order != MREPL)
160: error(Emount);
161:
162: pg = u->p->pgrp;
163: wlock(&pg->ns);
164: if(waserror()) {
165: wunlock(&pg->ns);
166: nexterror();
167: }
168:
169: l = &MOUNTH(pg, old);
170: for(m = *l; m; m = m->hash) {
171: if(eqchan(m->from, old, 1))
172: break;
173: l = &m->hash;
174: }
175:
176: if(m == 0) {
177: m = smalloc(sizeof(Mhead));
178: m->from = old;
179: incref(old);
180: m->hash = *l;
181: *l = m;
182: if(order != MREPL)
183: m->mount = newmount(m, old);
184: }
185:
186: if(m->mount && order == MREPL) {
187: mountfree(m->mount);
188: m->mount = 0;
189: }
190:
191: nm = newmount(m, new);
192: if(flag & MCREATE)
193: new->flag |= CCREATE;
194:
195: if(m->mount && order == MAFTER) {
196: for(f = m->mount; f->next; f = f->next)
197: ;
198: f->next = nm;
199: }
200: else {
201: nm->next = m->mount;
202: m->mount = nm;
203: }
204:
205: wunlock(&pg->ns);
206: poperror();
207: return nm->mountid;
208: }
209:
210: void
211: unmount(Chan *mnt, Chan *mounted)
212: {
213: Pgrp *pg;
214: Mhead *m, **l;
215: Mount *f, **p;
216: Chan *mc;
217:
218: pg = u->p->pgrp;
219: wlock(&pg->ns);
220:
221: l = &MOUNTH(pg, mnt);
222: for(m = *l; m; m = m->hash) {
223: if(eqchan(m->from, mnt, 1))
224: break;
225: l = &m->hash;
226: }
227:
228: if(m == 0) {
229: wunlock(&pg->ns);
230: error(Eunmount);
231: }
232:
233: if(mounted == 0) {
234: *l = m->hash;
235: wunlock(&pg->ns);
236: mountfree(m->mount);
237: close(m->from);
238: free(m);
239: return;
240: }
241:
242: p = &m->mount;
243: for(f = *p; f; f = f->next) {
244: mc = f->to->mchan;
245: if(eqchan(f->to, mounted, 1) || (mc && eqchan(mc, mounted, 1))) {
246: *p = f->next;
247: f->next = 0;
248: mountfree(f);
249: if(m->mount == 0) {
250: *l = m->hash;
251: wunlock(&pg->ns);
252: close(m->from);
253: free(m);
254: return;
255: }
256: wunlock(&pg->ns);
257: return;
258: }
259: p = &f->next;
260: }
261: wunlock(&pg->ns);
262: error(Eunion);
263: }
264:
265: Chan*
266: clone(Chan *c, Chan *nc)
267: {
268: return (*devtab[c->type].clone)(c, nc);
269: }
270:
271: Chan*
272: domount(Chan *c)
273: {
274: Pgrp *pg;
275: Chan *nc;
276: Mhead *m;
277:
278: pg = u->p->pgrp;
279: rlock(&pg->ns);
280: if(waserror()) {
281: runlock(&pg->ns);
282: nexterror();
283: }
284: c->mnt = 0;
285:
286: for(m = MOUNTH(pg, c); m; m = m->hash)
287: if(eqchan(m->from, c, 1)) {
288: nc = clone(m->mount->to, 0);
289: nc->mnt = m->mount;
290: nc->mountid = m->mount->mountid;
291: close(c);
292: c = nc;
293: break;
294: }
295:
296: poperror();
297: runlock(&pg->ns);
298: return c;
299: }
300:
301: Chan*
302: undomount(Chan *c)
303: {
304: Pgrp *pg;
305: Mhead **h, **he, *f;
306: Mount *t;
307:
308: pg = u->p->pgrp;
309: rlock(&pg->ns);
310: if(waserror()) {
311: runlock(&pg->ns);
312: nexterror();
313: }
314:
315: he = &pg->mnthash[MNTHASH];
316: for(h = pg->mnthash; h < he; h++) {
317: for(f = *h; f; f = f->hash) {
318: for(t = f->mount; t; t = t->next) {
319: if(eqchan(c, t->to, 1)) {
320: close(c);
321: c = clone(t->head->from, 0);
322: break;
323: }
324: }
325: }
326: }
327: poperror();
328: runlock(&pg->ns);
329: return c;
330: }
331:
332: Chan*
333: walk(Chan *ac, char *name, int domnt)
334: {
335: Pgrp *pg;
336: Chan *c = 0;
337: Mount *f;
338: int dotdot;
339:
340: if(*name == '\0')
341: return ac;
342:
343: dotdot = 0;
344: if(name[0] == '.')
345: if(name[1] == '.')
346: if(name[2] == '\0') {
347: ac = undomount(ac);
348: dotdot = 1;
349: }
350:
351: if((*devtab[ac->type].walk)(ac, name) != 0) {
352: if(dotdot)
353: ac = undomount(ac);
354: if(domnt)
355: ac = domount(ac);
356: return ac;
357: }
358:
359: if(ac->mnt == 0)
360: return 0;
361:
362: pg = u->p->pgrp;
363: rlock(&pg->ns);
364: if(waserror()) {
365: runlock(&pg->ns);
366: if(c)
367: close(c);
368: nexterror();
369: }
370: for(f = ac->mnt; f; f = f->next) {
371: c = clone(f->to, 0);
372: if((*devtab[c->type].walk)(c, name) != 0)
373: break;
374: close(c);
375: c = 0;
376: }
377: poperror();
378: runlock(&pg->ns);
379:
380: if(c) {
381: if(dotdot)
382: c = undomount(c);
383: c->mnt = 0;
384: if(domnt) {
385: if(waserror()) {
386: close(c);
387: nexterror();
388: }
389: c = domount(c);
390: poperror();
391: }
392: close(ac);
393: }
394: return c;
395: }
396:
397: /*
398: * c is a mounted non-creatable directory. find a creatable one.
399: */
400: Chan*
401: createdir(Chan *c)
402: {
403: Pgrp *pg;
404: Chan *nc;
405: Mount *f;
406:
407: pg = u->p->pgrp;
408: rlock(&pg->ns);
409: if(waserror()) {
410: runlock(&pg->ns);
411: nexterror();
412: }
413: for(f = c->mnt; f; f = f->next) {
414: if(f->to->flag&CCREATE) {
415: nc = clone(f->to, 0);
416: nc->mnt = f;
417: runlock(&pg->ns);
418: poperror();
419: close(c);
420: return nc;
421: }
422: }
423: error(Enocreate);
424: return 0; /* not reached */
425: }
426:
427: void
428: saveregisters(void)
429: {
430: }
431:
432: /*
433: * Turn a name into a channel.
434: * &name[0] is known to be a valid address. It may be a kernel address.
435: */
436: Chan*
437: namec(char *name, int amode, int omode, ulong perm)
438: {
439: Chan *c, *nc, *cc;
440: int t;
441: Rune r;
442: int mntok, isdot;
443: char *p;
444: char *elem;
445: char createerr[ERRLEN];
446:
447: if(name[0] == 0)
448: error(Enonexist);
449:
450: /*
451: * Make sure all of name is o.k. first byte is validated
452: * externally so if it's a kernel address we know it's o.k.
453: */
454: if(!((ulong)name & KZERO)){
455: p = name;
456: t = BY2PG-((ulong)p&(BY2PG-1));
457: while(vmemchr(p, 0, t) == 0){
458: p += t;
459: t = BY2PG;
460: }
461: }
462:
463: elem = u->elem;
464: mntok = 1;
465: isdot = 0;
466: if(name[0] == '/') {
467: c = clone(u->slash, 0);
468: /*
469: * Skip leading slashes.
470: */
471: name = skipslash(name);
472: }
473: else
474: if(name[0] == '#') {
475: mntok = 0;
476: name++;
477: name += chartorune(&r, name);
478: if(r == 'M')
479: error(Enonexist);
480: t = devno(r, 1);
481: if(t == -1)
482: error(Ebadsharp);
483: if(*name == '/'){
484: name = skipslash(name);
485: elem[0]=0;
486: }else
487: name = nextelem(name, elem);
488: c = (*devtab[t].attach)(elem);
489: }
490: else {
491: c = clone(u->dot, 0);
492: name = skipslash(name); /* eat leading ./ */
493: if(*name == 0)
494: isdot = 1;
495: }
496:
497: if(waserror()){
498: close(c);
499: nexterror();
500: }
501:
502: name = nextelem(name, elem);
503:
504: /*
505: * If mounting, don't follow the mount entry for root or the
506: * current directory.
507: */
508: if(mntok && !isdot && !(amode==Amount && elem[0]==0))
509: c = domount(c); /* see case Atodir below */
510:
511: /*
512: * How to treat the last element of the name depends on the operation.
513: * Therefore do all but the last element by the easy algorithm.
514: */
515: while(*name){
516: if((nc=walk(c, elem, mntok)) == 0)
517: error(Enonexist);
518: c = nc;
519: name = nextelem(name, elem);
520: }
521:
522: /*
523: * Last element; act according to type of access.
524: */
525: switch(amode){
526: case Aaccess:
527: if(isdot)
528: c = domount(c);
529: else{
530: if((nc=walk(c, elem, mntok)) == 0)
531: error(Enonexist);
532: c = nc;
533: }
534: break;
535:
536: case Atodir:
537: /*
538: * Directories (e.g. for cd) are left before the mount point,
539: * so one may mount on / or . and see the effect.
540: */
541: if((nc=walk(c, elem, 0)) == 0)
542: error(Enonexist);
543: c = nc;
544: if(!(c->qid.path & CHDIR))
545: error(Enotdir);
546: break;
547:
548: case Aopen:
549: if(isdot)
550: c = domount(c);
551: else{
552: if((nc=walk(c, elem, mntok)) == 0)
553: error(Enonexist);
554: c = nc;
555: }
556: Open:
557: /* else error() in open has wrong value of c saved */
558: saveregisters();
559: c = (*devtab[c->type].open)(c, omode);
560: if(omode & OCEXEC)
561: c->flag |= CCEXEC;
562: if(omode & ORCLOSE)
563: c->flag |= CRCLOSE;
564: break;
565:
566: case Amount:
567: /*
568: * When mounting on an already mounted upon directory, one wants
569: * subsequent mounts to be attached to the original directory, not
570: * the replacement.
571: */
572: if((nc=walk(c, elem, 0)) == 0)
573: error(Enonexist);
574: c = nc;
575: break;
576:
577: case Acreate:
578: if(isdot)
579: error(Eisdir);
580:
581: /*
582: * Walk the element before trying to create it
583: * to see if it exists. We clone the channel
584: * first, just in case someone is trying to
585: * use clwalk outside the kernel.
586: */
587: cc = clone(c, 0);
588: if(waserror()){
589: close(cc);
590: nexterror();
591: }
592: nameok(elem);
593: if((nc=walk(cc, elem, 1)) != 0){
594: poperror();
595: close(c);
596: c = nc;
597: omode |= OTRUNC;
598: goto Open;
599: }
600: close(cc);
601: poperror();
602:
603: /*
604: * the file didn't exist, try the create
605: */
606: if(c->mnt && !(c->flag&CCREATE))
607: c = createdir(c);
608:
609: /*
610: * protect against the open/create race. This is not a complete
611: * fix. It just reduces the window.
612: */
613: if(waserror()) {
614: strcpy(createerr, u->error);
615: nc = walk(c, elem, 1);
616: if(nc == 0)
617: error(createerr);
618: c = nc;
619: omode |= OTRUNC;
620: goto Open;
621: }
622: (*devtab[c->type].create)(c, elem, omode, perm);
623: if(omode & OCEXEC)
624: c->flag |= CCEXEC;
625: poperror();
626: break;
627:
628: default:
629: panic("unknown namec access %d\n", amode);
630: }
631: poperror();
632: return c;
633: }
634:
635: /*
636: * name[0] is addressable.
637: */
638: char*
639: skipslash(char *name)
640: {
641: Again:
642: while(*name == '/')
643: name++;
644: if(*name=='.' && (name[1]==0 || name[1]=='/')){
645: name++;
646: goto Again;
647: }
648: return name;
649: }
650:
651: char isfrog[256]={
652: /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1,
653: /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1,
654: /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1,
655: /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1,
656: [' '] 1,
657: ['/'] 1,
658: [0x7f] 1,
659: };
660:
661: void
662: nameok(char *elem)
663: {
664: char *eelem;
665:
666: eelem = elem+NAMELEN;
667: while(*elem) {
668: if(isfrog[*(uchar*)elem])
669: error(Ebadchar);
670: elem++;
671: if(elem >= eelem)
672: error(Efilename);
673: }
674: }
675:
676: /*
677: * name[0] should not be a slash.
678: */
679: char*
680: nextelem(char *name, char *elem)
681: {
682: int w;
683: char *nend;
684: Rune r;
685:
686: if(*name == '/')
687: error(Efilename);
688: nend = utfrune(name, '/');
689: if(nend == 0)
690: nend = strchr(name, 0);
691: w = nend-name;
692: if(w >= NAMELEN)
693: error(Efilename);
694: memmove(elem, name, w);
695: elem[w] = 0;
696: while(name < nend){
697: name += chartorune(&r, name);
698: if(r<sizeof(isfrog) && isfrog[r])
699: error(Ebadchar);
700: }
701: return skipslash(name);
702: }
703:
704: void
705: isdir(Chan *c)
706: {
707: if(c->qid.path & CHDIR)
708: return;
709: error(Enotdir);
710: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.