|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/systm.h"
3: #include "sys/inode.h"
4: #include "sys/dir.h"
5: #include "sys/user.h"
6: #include "sys/proc.h"
7: #include "sys/stat.h"
8: #include "sys/neta.h"
9: #include "sys/buf.h"
10: #include "sys/stream.h"
11: #include "sys/conf.h"
12:
13: /*
14: * obsolete network filesystem protocol
15: *
16: * i_fsflags is used in various places instead of the
17: * obsolete i_key
18: * this is a cheat
19: * it is allowed only because neta will soon vanish
20: */
21:
22: struct senda nilx;
23: static long natrannum;
24: #define ND 100
25: struct {
26: char len, s, n;
27: struct senda x[ND];
28: struct rcva y[ND];
29: } netabuf = {ND};
30: #define addx(z) netabuf.x[netabuf.n] = *z; netabuf.s = 1;
31: #define addy(z) netabuf.y[netabuf.n++] = *z; if(netabuf.n >= ND) netabuf.n = 0; netabuf.s = 0;
32:
33: int naput(), naupdat(), naread(), nawrite(), natrunc(), nastat();
34: int nanami(), namount();
35: struct fstypsw nafs =
36: fsinit(naput, naupdat, naread, nawrite, natrunc, nastat,
37: nanami, namount, nodev, nullopen, nodev);
38:
39: namount(sip, ip, flag, mnt, fstyp)
40: struct inode *ip, *sip;
41: {
42: if (!suser())
43: return;
44: if (mnt)
45: nadomount(sip, ip, flag, fstyp);
46: else
47: naunmount(ip, fstyp);
48: }
49:
50: nadomount(cip, dip, flag, fstyp)
51: register struct inode *cip, *dip;
52: {
53: struct inode pi;
54: register struct inode *rip;
55:
56: if(cip->i_sptr == NULL) {
57: u.u_error = ENXIO;
58: return;
59: }
60: if((dip->i_mode & IFMT) != IFDIR) {
61: u.u_error = ENOTDIR;
62: return;
63: }
64: /*
65: * take care, because of the stupid user-generated device
66: */
67: if (dip->i_fstyp == fstyp && dip->i_dev == flag) {
68: u.u_error = EBUSY;
69: return;
70: }
71: pi.i_dev = flag;
72: pi.i_fstyp = fstyp;
73: if ((rip = iget(&pi, flag, ROOTINO)) == NULL)
74: return;
75: if (rip->i_count > 1) {
76: iput(rip);
77: u.u_error = EBUSY;
78: return;
79: }
80: /*
81: * fake the root, rather than sending NAGET now,
82: * to avoid a deadlock when a server mounts itself
83: * the next stat will correct it
84: */
85: rip->i_mode = IFDIR|0555;
86: rip->i_un.i_tag = (flag<<16)|ROOTINO;
87: rip->i_un.i_cip = cip;
88: rip->i_nlink = 2;
89: rip->i_size = 32;
90: rip->i_uid = rip->i_gid = -1;
91: dip->i_mroot = rip;
92: rip->i_mpoint = dip;
93: prele(rip);
94: dip->i_count++;
95: cip->i_count++;
96: cip->i_un.i_fsflags = 0;
97: }
98:
99: naunmount(mip, fstyp)
100: register struct inode *mip;
101: {
102: register struct inode *rip;
103:
104: rip = mip->i_mroot;
105: plock(rip);
106: xumount(rip); /* shared text from remote root */
107: if (rip->i_count > 1 || ifsbusy(rip)) {
108: u.u_error = EBUSY;
109: prele(rip);
110: return;
111: }
112: plock(mip);
113: mip->i_mroot = NULL;
114: iput(mip);
115: if ((mip = rip->i_un.i_cip) == NULL)
116: panic("naunmount");
117: iput(rip);
118: iput(mip);
119: }
120:
121: naput(ip)
122: struct inode *ip;
123: { struct senda x;
124: struct rcva y;
125:
126: if (ip->i_un.i_cip == NULL)
127: return; /* obscure gmount safety */
128: if(ip->i_flag & ICHG)
129: naupdat(ip, &time, &time, 0);
130: x = nilx;
131: x.trannum = natrannum++;
132: x.cmd = NPUT;
133: x.uid = u.u_uid;
134: x.tag = ip->i_un.i_tag;
135: x.dev = ip->i_dev;
136: x.ino = ip->i_number;
137: send(ip->i_un.i_cip, &x, &y);
138: if(y.errno)
139: u.u_error = y.errno;
140: }
141:
142: /*
143: * special case:
144: * the root is faked up locally
145: * really just to avoid a silly deadlock in the face server
146: */
147: nafillin(fip, ip)
148: struct inode *fip;
149: register struct inode *ip;
150: { struct senda x;
151: struct rcva y;
152:
153: ip->i_un.i_cip = NULL; /* in case we have to put it */
154: if (fip->i_un.i_cip == NULL) {
155: u.u_error = ENXIO;
156: iput(ip);
157: return (-1);
158: }
159: x = nilx;
160: x.trannum = natrannum++;
161: x.cmd = NGET;
162: x.uid = u.u_uid;
163: x.dev = ip->i_dev;
164: x.ino = ip->i_number;
165: send(fip->i_un.i_cip, &x, &y);
166: if(y.errno == 0) {
167: ip->i_mode = y.mode;
168: ip->i_un.i_tag = y.tag;
169: ip->i_un.i_cip = fip->i_un.i_cip;
170: ip->i_nlink = y.nlink;
171: ip->i_size = y.size;
172: ip->i_uid = y.uid;
173: ip->i_gid = y.gid;
174: return (0);
175: }
176: iput(ip);
177: u.u_error = y.errno;
178: return(-1);
179: }
180:
181: /* this is used by CREAT */
182: naupdat(ip, ta, tm, waitfor)
183: struct inode *ip;
184: time_t *ta, *tm;
185: { struct senda x;
186: struct rcva y;
187:
188: if (ip->i_un.i_cip == NULL)
189: return; /* obscure gmount safety */
190: x = nilx;
191: x.trannum = natrannum++;
192: x.cmd = NUPDAT;
193: x.uid = u.u_uid;
194: x.gid = u.u_gid;
195: x.newuid = ip->i_uid;
196: x.newgid = ip->i_gid;
197: x.mode = ip->i_mode;
198: x.tag = ip->i_un.i_tag;
199: x.dev = ip->i_dev;
200: x.ino = ip->i_number;
201: if(ip->i_flag & IACC)
202: x.ta = *ta;
203: else
204: x.ta = 0;
205: if(ip->i_flag & ICHG)
206: x.tm = *tm;
207: else
208: x.tm = 0;
209: send(ip->i_un.i_cip, &x, &y);
210: if(y.errno) {
211: u.u_error = y.errno;
212: return;
213: }
214: ip->i_mode = y.mode;
215: ip->i_nlink = y.nlink;
216: ip->i_size = y.size;
217: ip->i_uid = y.uid;
218: ip->i_gid = y.gid;
219: ip->i_flag &= ~(IUPD|IACC|ICHG);
220: }
221:
222: naread(ip)
223: struct inode *ip;
224: { struct senda x;
225: struct rcva y;
226: struct buf *bp;
227: int n;
228:
229: bp = geteblk();
230: clrbuf(bp); /* could use user's buffer */
231: x = nilx;
232: x.trannum = natrannum++;
233: x.cmd = NREAD;
234: x.uid = u.u_uid;
235: x.tag = ip->i_un.i_tag;
236: x.dev = ip->i_dev;
237: x.ino = ip->i_number;
238: x.buf = bp->b_un.b_addr;
239: do {
240: n = u.u_count;
241: if(n > BUFSIZE)
242: n = BUFSIZE;
243: x.count = n;
244: x.offset = Ltol(u.u_offset);
245: send(ip->i_un.i_cip, &x, &y);
246: if((n = y.count) > 0) {
247: if(u.u_segflg != SEGSYS) {
248: if(copyout(bp->b_un.b_addr, u.u_base, n)) {
249: u.u_error = EFAULT;
250: break;
251: }
252: }
253: else
254: bcopy(bp->b_un.b_addr, u.u_base, n);
255: u.u_base += n;
256: u.u_offset = Lladd(u.u_offset, n);
257: u.u_count -= n;
258: }
259: if(y.errno)
260: u.u_error = y.errno;
261: } while(u.u_error == 0 && u.u_count != 0 && n > 0);
262: brelse(bp);
263: }
264: nawrite(ip)
265: struct inode *ip;
266: { struct senda x;
267: struct rcva y;
268: struct buf *bp;
269: int n;
270:
271: bp = geteblk();
272: x = nilx;
273: x.trannum = natrannum++;
274: x.cmd = NWRT;
275: x.uid = u.u_uid;
276: x.tag = ip->i_un.i_tag;
277: x.dev = ip->i_dev;
278: x.ino = ip->i_number;
279: x.buf = bp->b_un.b_addr;
280: do {
281: n = u.u_count;
282: if(n > BUFSIZE) /* should be bufsiz, but ... */
283: n = BUFSIZE;
284: if(u.u_segflg != SEGSYS) {
285: if(copyin(u.u_base, bp->b_un.b_addr, n)) {
286: u.u_error = EFAULT;
287: break;
288: }
289: }
290: else
291: bcopy(u.u_base, bp->b_un.b_addr, n);
292: x.count = n;
293: x.offset = Ltol(u.u_offset);
294: send(ip->i_un.i_cip, &x, &y);
295: if(y.errno) {
296: u.u_error = y.errno;
297: break;
298: }
299: ip->i_flag |= IUPD|ICHG;
300: u.u_count -= n;
301: u.u_offset = Lladd(u.u_offset, n);
302: u.u_base += n;
303: } while(u.u_error == 0 && u.u_count != 0);
304: brelse(bp);
305: }
306:
307: natrunc(ip)
308: struct inode *ip;
309: { struct senda x;
310: struct rcva y;
311:
312: x = nilx;
313: x.trannum = natrannum++;
314: x.cmd = NTRUNC;
315: x.uid = u.u_uid;
316: x.tag = ip->i_un.i_tag;
317: x.dev = ip->i_dev;
318: x.ino = ip->i_number;
319: send(ip->i_un.i_cip, &x, &y);
320: if(y.errno)
321: u.u_error = y.errno;
322: }
323:
324: nastat(ip, ub)
325: struct inode *ip;
326: struct stat *ub;
327: { struct senda x;
328: struct rcva y;
329: struct stat ds;
330:
331: x = nilx;
332: x.trannum = natrannum++;
333: x.cmd = NSTAT;
334: x.uid = u.u_uid;
335: x.tag = ip->i_un.i_tag;
336: x.dev = ip->i_dev;
337: x.ino = ip->i_number;
338: x.ta = time;
339: send(ip->i_un.i_cip, &x, &y);
340: if(y.errno) {
341: u.u_error = y.errno;
342: return;
343: }
344: ds.st_dev = ip->i_dev;
345: ds.st_ino = ip->i_number;
346: ip->i_mode = ds.st_mode = y.mode;
347: ip->i_nlink = ds.st_nlink = y.nlink;
348: ip->i_uid = ds.st_uid = y.uid;
349: ip->i_gid = ds.st_gid = y.gid;
350: ds.st_size = ip->i_size = y.size;
351: ds.st_atime = y.tm[0];
352: ds.st_mtime = y.tm[1];
353: ds.st_ctime = y.tm[2];
354: if(copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
355: u.u_error = EFAULT;
356: }
357:
358: /* a lot like fsnami */
359: nanami(p, flagp, follow)
360: struct nx *p;
361: struct argnamei *flagp;
362: { register struct inode *dp, *dip;
363: register char *cp;
364: int i, fstyp;
365: dev_t d;
366: struct direct dent;
367: struct senda x;
368: struct rcva y;
369:
370: cp = p->cp;
371: dp = p->dp;
372: x = nilx;
373: x.cmd = NNAMI;
374: x.uid = u.u_uid;
375: x.gid = u.u_gid;
376:
377: /*
378: * dp must be a directory and
379: * must have X permission.
380: * cp is a path name relative to that directory.
381: */
382:
383: dirloop:
384: if((dp->i_mode&IFMT) != IFDIR)
385: u.u_error = ENOTDIR;
386: (void) access(dp, IEXEC);
387: for (i=0; *cp!='\0' && *cp!='/'; i++) {
388: if (i >= DIRSIZ) {
389: u.u_error = ENOENT;
390: break;
391: }
392: dent.d_name[i] = *cp++;
393: }
394: if(u.u_error)
395: goto outnull;
396: while (i < DIRSIZ)
397: dent.d_name[i++] = '\0';
398: if (dent.d_name[0] == '\0') { /* null name, e.g. "/" or "" */
399: if (flagp->flag != NI_SEARCH) {
400: u.u_error = ENOENT;
401: goto outnull;
402: }
403: goto out;
404: }
405: u.u_segflg = SEGSYS;
406:
407: /* send off the request, get back ino, dev, flagp stuff */
408: x.trannum = natrannum++;
409: x.tag = dp->i_un.i_tag;
410: x.dev = dp->i_dev;
411: x.ino = dp->i_number;
412: x.count = DIRSIZ;
413: x.buf = dent.d_name;
414: while(*cp == '/')
415: cp++;
416: if(*cp=='\0') {
417: switch(flagp->flag) {
418: case NI_SEARCH:
419: x.flags = NSEARCH;
420: break;
421: case NI_DEL:
422: x.flags = NDEL;
423: break;
424: case NI_LINK:
425: x.flags = NLINK;
426: x.dev = flagp->un.il->i_dev;
427: x.ino = flagp->un.il->i_number;
428: break;
429: case NI_CREAT:
430: case NI_NXCREAT:
431: x.flags = NCREAT;
432: x.mode = flagp->un.mode;
433: break;
434: case NI_MKDIR:
435: x.flags = NMKDIR;
436: x.mode = flagp->un.mode;
437: break;
438: case NI_RMDIR:
439: x.flags = NRMDIR;
440: break;
441: default:
442: u.u_error = ENXIO;
443: goto outnull;
444: }
445: }
446: send(dp->i_un.i_cip, &x, &y);
447: if(y.errno) {
448: u.u_error = y.errno;
449: goto outnull;
450: }
451: if(y.flags == NOMATCH)
452: goto nomatch;
453: dent.d_ino = y.ino;
454: if (y.ino == 0) {
455: printf("y.ino 0 in nanami\n");
456: u.u_error = ENOENT;
457: goto outnull;
458: }
459: d = y.dev;
460:
461: if(*cp == 0 && (flagp->flag==NI_DEL || flagp->flag==NI_RMDIR)) {
462: /* delete the entry, server did all but xrele */
463: dip = iget(dp, d, dent.d_ino);
464: if (dip == NULL)
465: goto outnull;
466: if (dip->i_count == 1) {
467: dip->i_un.i_cip = NULL;
468: iput(dip);
469: goto outnull;
470: }
471: if(dip->i_flag&ITEXT)
472: xrele(dip); /* free busy text */
473: dip->i_nlink--;
474: dip->i_flag |= ICHG;
475: iput(dip);
476: goto outnull;
477: }
478: /*
479: * Special handling for ".."
480: */
481: fstyp = dp->i_fstyp;
482:
483: if(y.flags == NROOT) { /* popped out of net fs */
484: if (dp == u.u_rdir)
485: dent.d_ino = dp->i_number;
486: else if (dp != rootdir && dent.d_ino==ROOTINO
487: && dp->i_number == ROOTINO) {
488: if ((dip = dp->i_mpoint) == NULL)
489: panic("namei: mpoint");
490: iput(dp);
491: dp = dip;
492: plock(dp);
493: dp->i_count++;
494: /* was there always .. there? */
495: if(*cp && cp < p->nbuf + 3)
496: panic("nanami");
497: if(!*cp && cp < p->nbuf + 2)
498: panic("nanami2");
499: if(*cp)
500: *--cp = '/';
501: *--cp = '.';
502: *--cp = '.';
503: if(fstyp != dp->i_fstyp)
504: goto more;
505: goto dirloop;
506: }
507: }
508: dip = dp;
509: prele(dip);
510: dp = iget(dip, d, dent.d_ino);
511: if(dp == NULL) {
512: iput(dip);
513: goto out;
514: }
515: if (dp->i_count == 1 && nafillin(dip, dp) < 0) {
516: iput(dip);
517: dp = NULL;
518: goto out;
519: }
520: if(fstyp != dp->i_fstyp) {
521: iput(dip);
522: goto more;
523: }
524: /*
525: * Check for symbolic link
526: */
527: if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp)) {
528: char *ocp;
529:
530: ocp = cp;
531: while (*cp++)
532: ;
533: if (dp->i_size + (cp-ocp) >= p->nlen-1
534: || ++p->nlink>8) {
535: u.u_error = ELOOP;
536: iput(dip);
537: goto outnull;
538: }
539: bcopy(ocp, p->nbuf+dp->i_size + 1, cp-ocp);
540: *(p->nbuf + dp->i_size) = '/';
541: u.u_base = p->nbuf;
542: u.u_count = dp->i_size;
543: u.u_offset = ltoL(0);
544: readi(dp);
545: if(u.u_error) {
546: iput(dip);
547: goto outnull;
548: }
549: cp = p->nbuf;
550: iput(dp);
551: if (*cp == '/') {
552: iput(dip);
553: while (*cp == '/')
554: cp++;
555: if ((dp = u.u_rdir) == NULL)
556: dp = rootdir;
557: plock(dp);
558: dp->i_count++;
559: } else {
560: dp = dip;
561: plock(dp);
562: }
563: if(fstyp != dp->i_fstyp)
564: goto more;
565: goto dirloop;
566: }
567: iput(dip);
568: if(*cp)
569: goto dirloop;
570: if(flagp->flag == NI_SEARCH && flagp->un.buf)
571: bcopy((caddr_t)dent.d_name, flagp->un.buf, flagp->len);
572: goto out;
573:
574: nomatch:
575: /*
576: * Search failed.
577: */
578: switch(flagp->flag) { /* probably creating a new file */
579: case NI_LINK: /* make a link */
580: case NI_MKDIR: /* make directory */
581: goto outnull;
582: case NI_CREAT: /* create a new file */
583: case NI_NXCREAT:
584: if(y.errno == EACCES || y.ino == 0) {
585: u.u_error = EACCES;
586: goto outnull;
587: }
588: dip = iget(dp, y.dev, y.ino);
589: if(dip == NULL)
590: goto outnull;
591: if (dip->i_count == 1 && nafillin(dp, dip) < 0)
592: goto outnull;
593: iput(dp);
594: dp = dip;
595: flagp->un.mode = ~flagp->un.mode;
596: goto out;
597:
598: default:
599: u.u_error = ENOENT;
600: goto outnull;
601: }
602:
603: out:
604: p->dp = dp;
605: return (0);
606:
607: outnull:
608: iput(dp);
609: p->dp = NULL;
610: return (0);
611:
612: more:
613: p->cp = cp;
614: p->dp = dp;
615: return (1);
616: }
617:
618: struct {
619: int tran;
620: short proc, dev;
621: } ntx[32]; /* more debuggery */
622: send(cip, x, y)
623: struct inode *cip;
624: struct senda *x;
625: struct rcva *y;
626: { int n, tn, ix;
627: x->version = NETVERSION;
628: /* until demux works, use key as a lock */
629: while(cip->i_un.i_fsflags)
630: sleep((caddr_t)cip, PZERO);
631: cip->i_un.i_fsflags = 1;
632: tn = x->trannum;
633: netabuf.s = 2;
634: for(ix = 0; ntx[ix].tran && ix < 32; ix++) {
635: ntx[ix].tran = tn;
636: ntx[ix].proc = u.u_procp->p_pid;
637: ntx[ix].dev = x->dev;
638: }
639: n = istwrite(cip, (char *)x, sizeof(*x));
640: netabuf.s = 3;
641: if(n == -1) {
642: y->errno = EIO;
643: goto bad;
644: }
645: netabuf.s = 4;
646: if(x->count > 0 && x->buf && x->cmd != NREAD) {
647: n = istwrite(cip, x->buf, x->count);
648: if(n == -1)
649: goto bad;
650: }
651: readagain:
652: netabuf.s = 5;
653: n = istread(cip, (char *)y, sizeof(*y), 0);
654: netabuf.s = 6;
655: if(n != sizeof(*y))
656: goto bad;
657: if(y->errno == 0 && x->cmd == NREAD) {
658: n = istread(cip, x->buf, y->count, 0);
659: if(n != y->count) {
660: printf("neta: read %d expected %d\n", n, y->count);
661: /* shut it down */
662: istwrite(cip, (char *)x, 0);
663: goto bad;
664: }
665: }
666: if(y->errno == 0) {
667: if(y->trannum != tn) {
668: if(y->trannum < tn) /* distant past */
669: goto readagain;
670: printf("neta: sent %d got %d\n", tn, y->trannum);
671: goto bad;
672: }
673: addx(x);
674: addy(y);
675: if(ix < 32)
676: ntx[ix].tran = 0;
677: cip->i_un.i_fsflags = 0;
678: wakeup((caddr_t)cip);
679: return;
680: }
681: bad:
682: cip->i_un.i_fsflags = 0;
683: if(ix < 32)
684: ntx[ix].tran = 0;
685: for(ix = 0; ix < 32; ix++)
686: if(ntx[ix].tran)
687: printf("tran %d proc %d 0x%x\n", ntx[ix].tran, ntx[ix].proc, ntx[ix].dev);
688: wakeup((caddr_t)cip);
689: addx(x);
690: addy(y);
691: if(y->errno)
692: return;
693: y->errno = EIO;
694: }
695: static struct D { struct D *a; char *b;} VER = {&VER,"\n85/6/9:neta.c\n"};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.