|
|
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: /*
9: * The sys*() routines needn't poperror() as they return directly to syscall().
10: */
11:
12: int
13: newfd(Chan *c)
14: {
15: Fgrp *f = u->p->fgrp;
16: int i;
17:
18: lock(f);
19: for(i=0; i<NFD; i++)
20: if(f->fd[i] == 0){
21: if(i > f->maxfd)
22: f->maxfd = i;
23: f->fd[i] = c;
24: unlock(f);
25: return i;
26: }
27: unlock(f);
28: exhausted("file descriptors");
29: return 0;
30: }
31:
32: Chan*
33: fdtochan(int fd, int mode, int chkmnt, int iref)
34: {
35: Chan *c;
36: Fgrp *f;
37:
38: c = 0;
39: f = u->p->fgrp;
40:
41: lock(f);
42: if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) {
43: unlock(f);
44: error(Ebadfd);
45: }
46: if(iref)
47: incref(c);
48: unlock(f);
49:
50: if(chkmnt && (c->flag&CMSG)) {
51: if(iref)
52: close(c);
53: error(Ebadusefd);
54: }
55:
56: if(mode<0 || c->mode==ORDWR)
57: return c;
58:
59: if((mode&OTRUNC) && c->mode==OREAD) {
60: if(iref)
61: close(c);
62: error(Ebadusefd);
63: }
64:
65: if((mode&~OTRUNC) != c->mode) {
66: if(iref)
67: close(c);
68: error(Ebadusefd);
69: }
70:
71: return c;
72: }
73:
74: int
75: openmode(ulong o)
76: {
77: if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC))
78: error(Ebadarg);
79: o &= ~(OTRUNC|OCEXEC|ORCLOSE);
80: if(o > OEXEC)
81: error(Ebadarg);
82: if(o == OEXEC)
83: return OREAD;
84: return o;
85: }
86:
87: long
88: syspipe(ulong *arg)
89: {
90: int fd[2];
91: Chan *c[2];
92: Dev *d;
93: Fgrp *f = u->p->fgrp;
94:
95: validaddr(arg[0], 2*BY2WD, 1);
96: evenaddr(arg[0]);
97: d = &devtab[devno('|', 0)];
98: c[0] = (*d->attach)(0);
99: c[1] = 0;
100: fd[0] = -1;
101: fd[1] = -1;
102: if(waserror()){
103: close(c[0]);
104: if(c[1])
105: close(c[1]);
106: if(fd[0] >= 0)
107: f->fd[fd[0]]=0;
108: if(fd[1] >= 0)
109: f->fd[fd[1]]=0;
110: nexterror();
111: }
112: c[1] = (*d->clone)(c[0], 0);
113: (*d->walk)(c[0], "data");
114: (*d->walk)(c[1], "data1");
115: c[0] = (*d->open)(c[0], ORDWR);
116: c[1] = (*d->open)(c[1], ORDWR);
117: fd[0] = newfd(c[0]);
118: fd[1] = newfd(c[1]);
119: ((long*)arg[0])[0] = fd[0];
120: ((long*)arg[0])[1] = fd[1];
121: poperror();
122: return 0;
123: }
124:
125: long
126: sysdup(ulong *arg)
127: {
128: int fd;
129: Chan *c, *oc;
130: Fgrp *f = u->p->fgrp;
131:
132: /*
133: * Close after dup'ing, so date > #d/1 works
134: */
135: c = fdtochan(arg[0], -1, 0, 1);
136: fd = arg[1];
137: if(fd != -1){
138: if(fd<0 || NFD<=fd) {
139: close(c);
140: error(Ebadfd);
141: }
142: lock(f);
143: if(fd > f->maxfd)
144: f->maxfd = fd;
145:
146: oc = f->fd[fd];
147: f->fd[fd] = c;
148: unlock(f);
149: if(oc)
150: close(oc);
151: }else{
152: if(waserror()) {
153: close(c);
154: nexterror();
155: }
156: fd = newfd(c);
157: poperror();
158: }
159:
160: return fd;
161: }
162:
163: long
164: sysopen(ulong *arg)
165: {
166: int fd;
167: Chan *c = 0;
168:
169: openmode(arg[1]); /* error check only */
170: if(waserror()){
171: if(c)
172: close(c);
173: nexterror();
174: }
175: validaddr(arg[0], 1, 0);
176: c = namec((char*)arg[0], Aopen, arg[1], 0);
177: fd = newfd(c);
178: poperror();
179: return fd;
180: }
181:
182: void
183: fdclose(int fd, int flag)
184: {
185: int i;
186: Chan *c;
187: Fgrp *f = u->p->fgrp;
188:
189: lock(f);
190: c = f->fd[fd];
191: if(c == 0){
192: /* can happen for users with shared fd tables */
193: unlock(f);
194: return;
195: }
196: if(flag){
197: if(c==0 || !(c->flag&flag)){
198: unlock(f);
199: return;
200: }
201: }
202: f->fd[fd] = 0;
203: if(fd == f->maxfd)
204: for(i=fd; --i>=0 && f->fd[i]==0; )
205: f->maxfd = i;
206:
207: unlock(f);
208: close(c);
209: }
210:
211: long
212: sysclose(ulong *arg)
213: {
214: fdtochan(arg[0], -1, 0, 0);
215: fdclose(arg[0], 0);
216:
217: return 0;
218: }
219:
220: long
221: unionread(Chan *c, void *va, long n)
222: {
223: long nr;
224: Chan *nc;
225: Pgrp *pg;
226:
227: pg = u->p->pgrp;
228: rlock(&pg->ns);
229:
230: for(;;) {
231: /* Error causes component of union to be skipped */
232: if(waserror())
233: goto next;
234:
235: nc = clone(c->mnt->to, 0);
236: poperror();
237:
238: if(c->mountid != c->mnt->mountid) {
239: pprint("unionread: changed underfoot?\n");
240: runlock(&pg->ns);
241: close(nc);
242: return 0;
243: }
244:
245: if(waserror()) {
246: close(nc);
247: goto next;
248: }
249:
250: nc = (*devtab[nc->type].open)(nc, OREAD);
251: nc->offset = c->offset;
252: nr = (*devtab[nc->type].read)(nc, va, n, nc->offset);
253: /* devdirread e.g. changes it */
254: c->offset = nc->offset;
255: poperror();
256:
257: close(nc);
258: if(nr > 0) {
259: runlock(&pg->ns);
260: return nr;
261: }
262: /* Advance to next element */
263: next:
264: c->mnt = c->mnt->next;
265: if(c->mnt == 0)
266: break;
267: c->mountid = c->mnt->mountid;
268: c->offset = 0;
269: }
270: runlock(&pg->ns);
271: return 0;
272: }
273:
274: long
275: sysread(ulong *arg)
276: {
277: int dir;
278: long n;
279: Chan *c;
280:
281: validaddr(arg[1], arg[2], 1);
282: c = fdtochan(arg[0], OREAD, 1, 1);
283: if(waserror()) {
284: close(c);
285: nexterror();
286: }
287:
288: n = arg[2];
289: dir = c->qid.path&CHDIR;
290:
291: if(dir) {
292: n -= n%DIRLEN;
293: if(c->offset%DIRLEN || n==0)
294: error(Etoosmall);
295: }
296:
297: if(dir && c->mnt)
298: n = unionread(c, (void*)arg[1], n);
299: else
300: n = (*devtab[c->type].read)(c, (void*)arg[1], n, c->offset);
301:
302: lock(c);
303: c->offset += n;
304: unlock(c);
305:
306: poperror();
307: close(c);
308:
309: return n;
310: }
311:
312: long
313: syswrite(ulong *arg)
314: {
315: Chan *c;
316: long n;
317:
318: validaddr(arg[1], arg[2], 0);
319: c = fdtochan(arg[0], OWRITE, 1, 1);
320: if(waserror()) {
321: close(c);
322: nexterror();
323: }
324:
325: if(c->qid.path & CHDIR)
326: error(Eisdir);
327:
328: n = (*devtab[c->type].write)(c, (void*)arg[1], arg[2], c->offset);
329:
330: lock(c);
331: c->offset += n;
332: unlock(c);
333:
334: poperror();
335: close(c);
336:
337: return n;
338: }
339:
340: long
341: sysseek(ulong *arg)
342: {
343: Chan *c;
344: char buf[DIRLEN];
345: Dir dir;
346: long off;
347:
348: c = fdtochan(arg[0], -1, 1, 0);
349: if(c->qid.path & CHDIR)
350: error(Eisdir);
351:
352: if(devchar[c->type] == '|')
353: error(Eisstream);
354:
355: off = 0;
356: switch(arg[2]){
357: case 0:
358: off = c->offset = arg[1];
359: break;
360:
361: case 1:
362: lock(c); /* lock for read/write update */
363: c->offset += (long)arg[1];
364: off = c->offset;
365: unlock(c);
366: break;
367:
368: case 2:
369: (*devtab[c->type].stat)(c, buf);
370: convM2D(buf, &dir);
371: c->offset = dir.length + (long)arg[1];
372: off = c->offset;
373: break;
374: }
375: return off;
376: }
377:
378: long
379: sysfstat(ulong *arg)
380: {
381: Chan *c;
382:
383: validaddr(arg[1], DIRLEN, 1);
384: evenaddr(arg[1]);
385: c = fdtochan(arg[0], -1, 0, 1);
386: if(waserror()) {
387: close(c);
388: nexterror();
389: }
390: (*devtab[c->type].stat)(c, (char*)arg[1]);
391: poperror();
392: close(c);
393: return 0;
394: }
395:
396: long
397: sysstat(ulong *arg)
398: {
399: Chan *c;
400:
401: validaddr(arg[1], DIRLEN, 1);
402: evenaddr(arg[1]);
403: validaddr(arg[0], 1, 0);
404: c = namec((char*)arg[0], Aaccess, 0, 0);
405: if(waserror()){
406: close(c);
407: nexterror();
408: }
409: (*devtab[c->type].stat)(c, (char*)arg[1]);
410: poperror();
411: close(c);
412: return 0;
413: }
414:
415: long
416: syschdir(ulong *arg)
417: {
418: Chan *c;
419:
420: validaddr(arg[0], 1, 0);
421: c = namec((char*)arg[0], Atodir, 0, 0);
422: close(u->dot);
423: u->dot = c;
424: return 0;
425: }
426:
427: long
428: bindmount(ulong *arg, int ismount)
429: {
430: Chan *c0, *c1, *bc;
431: ulong flag;
432: long ret;
433: int fd;
434: struct{
435: Chan *chan;
436: char *spec;
437: }bogus;
438:
439: flag = arg[2];
440: fd = arg[0];
441: if(flag>MMASK || (flag&MORDER)==(MBEFORE|MAFTER))
442: error(Ebadarg);
443: if(ismount){
444: bc = fdtochan(fd, 2, 0, 1);
445: if(waserror()) {
446: close(bc);
447: nexterror();
448: }
449: bogus.chan = bc;
450:
451: validaddr(arg[3], 1, 0);
452: if(vmemchr((char*)arg[3], '\0', NAMELEN) == 0)
453: error(Ebadarg);
454:
455: bogus.spec = (char*)arg[3];
456:
457: ret = devno('M', 0);
458: c0 = (*devtab[ret].attach)((char*)&bogus);
459:
460: poperror();
461: close(bc);
462: }
463: else {
464: validaddr(arg[0], 1, 0);
465: c0 = namec((char*)arg[0], Aaccess, 0, 0);
466: }
467: if(waserror()){
468: close(c0);
469: nexterror();
470: }
471: validaddr(arg[1], 1, 0);
472: c1 = namec((char*)arg[1], Amount, 0, 0);
473: if(waserror()){
474: close(c1);
475: nexterror();
476: }
477: if((c0->qid.path^c1->qid.path) & CHDIR)
478: error(Emount);
479: if(flag && !(c0->qid.path&CHDIR))
480: error(Emount);
481: ret = mount(c0, c1, flag);
482: poperror();
483: close(c1);
484: poperror();
485: close(c0);
486: if(ismount)
487: fdclose(fd, 0);
488: return ret;
489: }
490:
491: long
492: sysbind(ulong *arg)
493: {
494: return bindmount(arg, 0);
495: }
496:
497: long
498: sysmount(ulong *arg)
499: {
500: return bindmount(arg, 1);
501: }
502:
503: long
504: sysunmount(ulong *arg)
505: {
506: Chan *cmount, *cmounted;
507:
508: cmounted = 0;
509:
510: validaddr(arg[1], 1, 0);
511: cmount = namec((char *)arg[1], Amount, 0, 0);
512:
513: if(arg[0]) {
514: if(waserror()) {
515: close(cmount);
516: nexterror();
517: }
518: validaddr(arg[0], 1, 0);
519: cmounted = namec((char*)arg[0], Aopen, OREAD, 0);
520: poperror();
521: }
522:
523: if(waserror()) {
524: close(cmount);
525: if(cmounted)
526: close(cmounted);
527: nexterror();
528: }
529: unmount(cmount, cmounted);
530: close(cmount);
531: if(cmounted)
532: close(cmounted);
533: poperror();
534: return 0;
535: }
536:
537: long
538: syscreate(ulong *arg)
539: {
540: int fd;
541: Chan *c = 0;
542:
543: openmode(arg[1]); /* error check only */
544: if(waserror()) {
545: if(c)
546: close(c);
547: nexterror();
548: }
549: validaddr(arg[0], 1, 0);
550: c = namec((char*)arg[0], Acreate, arg[1], arg[2]);
551: fd = newfd(c);
552: poperror();
553: return fd;
554: }
555:
556: long
557: sysremove(ulong *arg)
558: {
559: Chan *c;
560:
561: validaddr(arg[0], 1, 0);
562: c = namec((char*)arg[0], Aaccess, 0, 0);
563: if(waserror()){
564: c->type = 0; /* see below */
565: close(c);
566: nexterror();
567: }
568: (*devtab[c->type].remove)(c);
569: /*
570: * Remove clunks the fid, but we need to recover the Chan
571: * so fake it up. rootclose() is known to be a nop.
572: */
573: c->type = 0;
574: poperror();
575: close(c);
576: return 0;
577: }
578:
579: long
580: syswstat(ulong *arg)
581: {
582: Chan *c;
583:
584: validaddr(arg[1], DIRLEN, 0);
585: nameok((char*)arg[1]);
586: validaddr(arg[0], 1, 0);
587: c = namec((char*)arg[0], Aaccess, 0, 0);
588: if(waserror()){
589: close(c);
590: nexterror();
591: }
592: (*devtab[c->type].wstat)(c, (char*)arg[1]);
593: poperror();
594: close(c);
595: return 0;
596: }
597:
598: long
599: sysfwstat(ulong *arg)
600: {
601: Chan *c;
602:
603: validaddr(arg[1], DIRLEN, 0);
604: nameok((char*)arg[1]);
605: c = fdtochan(arg[0], -1, 1, 1);
606: if(waserror()) {
607: close(c);
608: nexterror();
609: }
610: (*devtab[c->type].wstat)(c, (char*)arg[1]);
611: poperror();
612: close(c);
613: return 0;
614: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.