|
|
1.1 root 1: /*
2: * Copyright (c) 1990, 1992 Jan-Simon Pendry
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Jan-Simon Pendry.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: * $Id: fdesc_vnops.c,v 1.3 1993/03/30 05:16:56 cgd Exp $
37: */
38:
39: /*
40: * /dev/fd Filesystem
41: */
42:
43: #include "param.h"
44: #include "systm.h"
45: #include "types.h"
46: #include "time.h"
47: #include "proc.h"
48: #include "resourcevar.h"
49: #include "filedesc.h"
50: #include "vnode.h"
51: #include "file.h"
52: #include "stat.h"
53: #include "mount.h"
54: #include "namei.h"
55: #include "buf.h"
56: #include "miscfs/fdesc/fdesc.h"
57:
58: #include "../ufs/dir.h" /* For readdir() XXX */
59:
60: /*
61: * vp is the current namei directory
62: * ndp is the name to locate in that directory...
63: */
64: fdesc_lookup(dvp, ndp, p)
65: struct vnode *dvp;
66: struct nameidata *ndp;
67: struct proc *p;
68: {
69: char *pname = ndp->ni_ptr;
70: int nfiles = p->p_fd->fd_nfiles;
71: unsigned fd;
72: int error;
73: struct vnode *fvp;
74:
75: #ifdef FDESC_DIAGNOSTIC
76: printf("fdesc_lookup(%s)\n", pname);
77: #endif
78: if (ndp->ni_namelen == 1 && *pname == '.') {
79: ndp->ni_dvp = dvp;
80: ndp->ni_vp = dvp;
81: VREF(dvp);
82: /*VOP_LOCK(dvp);*/
83: return (0);
84: }
85:
86: fd = 0;
87: while (*pname >= '0' && *pname <= '9') {
88: fd = 10 * fd + *pname++ - '0';
89: if (fd >= nfiles)
90: break;
91: }
92:
93: #ifdef FDESC_DIAGNOSTIC
94: printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname);
95: #endif
96: if (*pname == '/') {
97: error = ENOTDIR;
98: goto bad;
99: }
100:
101: if (*pname != '\0') {
102: error = ENOENT;
103: goto bad;
104: }
105:
106: if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) {
107: error = EBADF;
108: goto bad;
109: }
110:
111: #ifdef FDESC_DIAGNOSTIC
112: printf("fdesc_lookup: allocate new vnode\n");
113: #endif
114: error = getnewvnode(VT_UFS, dvp->v_mount, &fdesc_vnodeops, &fvp);
115: if (error)
116: goto bad;
117: VTOFDESC(fvp)->f_fd = fd;
118: /*VTOFDESC(fvp)->f_isroot = 0;*/
119: ndp->ni_dvp = dvp;
120: ndp->ni_vp = fvp;
121: #ifdef FDESC_DIAGNOSTIC
122: printf("fdesc_lookup: newvp = %x\n", fvp);
123: #endif
124: return (0);
125:
126: bad:;
127: ndp->ni_dvp = dvp;
128: ndp->ni_vp = NULL;
129: #ifdef FDESC_DIAGNOSTIC
130: printf("fdesc_lookup: error = %d\n", error);
131: #endif
132: return (error);
133: }
134:
135: fdesc_open(vp, mode, cred, p)
136: struct vnode *vp;
137: int mode;
138: struct ucred *cred;
139: struct proc *p;
140: {
141: int error;
142: struct filedesc *fdp;
143: struct file *fp;
144: int dfd;
145: int fd;
146:
147: /*
148: * Can always open the root (modulo perms)
149: */
150: if (vp->v_flag & VROOT)
151: return (0);
152:
153: /*
154: * XXX Kludge: set p->p_dupfd to contain the value of the
155: * the file descriptor being sought for duplication. The error
156: * return ensures that the vnode for this device will be released
157: * by vn_open. Open will detect this special error and take the
158: * actions in dupfdopen. Other callers of vn_open or VOP_OPEN
159: * will simply report the error.
160: */
161: p->p_dupfd = VTOFDESC(vp)->f_fd; /* XXX */
162: return (ENODEV);
163: }
164:
165: static int
166: fdesc_attr(fd, vap, cred, p)
167: int fd;
168: struct vattr *vap;
169: struct ucred *cred;
170: struct proc *p;
171: {
172: struct filedesc *fdp = p->p_fd;
173: struct file *fp;
174: int error;
175:
176: #ifdef FDESC_DIAGNOSTIC
177: printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
178: #endif
179: if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
180: #ifdef FDESC_DIAGNOSTIC
181: printf("fdesc_attr: fp = %x (EBADF)\n", fp);
182: #endif
183: return (EBADF);
184: }
185:
186: /*
187: * Can stat the underlying vnode, but not sockets because
188: * they don't use struct vattrs. Well, we could convert from
189: * a struct stat back to a struct vattr, later...
190: */
191: switch (fp->f_type) {
192: case DTYPE_VNODE:
193: error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
194: break;
195:
196: case DTYPE_SOCKET:
197: error = EOPNOTSUPP;
198: break;
199:
200: default:
201: panic("fdesc attr");
202: break;
203: }
204:
205: #ifdef FDESC_DIAGNOSTIC
206: printf("fdesc_attr: returns error %d\n", error);
207: #endif
208: return (error);
209: }
210:
211: fdesc_getattr(vp, vap, cred, p)
212: struct vnode *vp;
213: struct vattr *vap;
214: struct ucred *cred;
215: struct proc *p;
216: {
217: unsigned fd;
218: int error;
219:
220: if (vp->v_flag & VROOT) {
221: #ifdef FDESC_DIAGNOSTIC
222: printf("fdesc_getattr: stat rootdir\n");
223: #endif
224: bzero((caddr_t) vap, sizeof(*vap));
225: vattr_null(vap);
226: vap->va_type = VDIR;
227: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
228: vap->va_nlink = 2;
229: vap->va_uid = 0;
230: vap->va_gid = 0;
231: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
232: vap->va_fileid = 2;
233: /* vap->va_qsize = 0; */
234: vap->va_size = DEV_BSIZE;
235: vap->va_blocksize = DEV_BSIZE;
236: microtime(&vap->va_atime);
237: vap->va_mtime = vap->va_atime;
238: vap->va_ctime = vap->va_ctime;
239: vap->va_gen = 0;
240: vap->va_flags = 0;
241: vap->va_rdev = 0;
242: /* vap->va_qbytes = 0; */
243: vap->va_bytes = 0;
244: return (0);
245: }
246:
247: fd = VTOFDESC(vp)->f_fd;
248: error = fdesc_attr(fd, vap, cred, p);
249: if (error == 0)
250: vp->v_type = vap->va_type;
251: return (error);
252: }
253:
254: fdesc_setattr(vp, vap, cred, p)
255: struct vnode *vp;
256: struct vattr *vap;
257: struct ucred *cred;
258: struct proc *p;
259: {
260: struct filedesc *fdp = p->p_fd;
261: struct file *fp;
262: unsigned fd;
263: int error;
264:
265: /*
266: * Can't mess with the root vnode
267: */
268: if (vp->v_flag & VROOT)
269: return (EACCES);
270:
271: fd = VTOFDESC(vp)->f_fd;
272: #ifdef FDESC_DIAGNOSTIC
273: printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
274: #endif
275: if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
276: #ifdef FDESC_DIAGNOSTIC
277: printf("fdesc_setattr: fp = %x (EBADF)\n", fp);
278: #endif
279: return (EBADF);
280: }
281:
282: /*
283: * Can setattr the underlying vnode, but not sockets!
284: */
285: switch (fp->f_type) {
286: case DTYPE_VNODE:
287: error = VOP_SETATTR((struct vnode *) fp->f_data, vap, cred, p);
288: break;
289:
290: case DTYPE_SOCKET:
291: error = EOPNOTSUPP;
292: break;
293:
294: default:
295: panic("fdesc setattr");
296: break;
297: }
298:
299: #ifdef FDESC_DIAGNOSTIC
300: printf("fdesc_setattr: returns error %d\n", error);
301: #endif
302: return (error);
303: }
304:
305: fdesc_readdir(vp, uio, cred, eofflagp)
306: struct vnode *vp;
307: struct uio *uio;
308: struct ucred *cred;
309: int *eofflagp;
310: {
311: struct filedesc *fdp;
312: int ind, i;
313: int error;
314:
315: #define UIO_MX 16
316:
317: fdp = uio->uio_procp->p_fd;
318: ind = uio->uio_offset / UIO_MX;
319: error = 0;
320: while (uio->uio_resid > 0) {
321: struct direct d;
322: struct direct *dp = &d;
323:
324: if (ind < 2) { /* . or .. */
325: bzero((caddr_t) dp, UIO_MX);
326: if (ind == 0) {
327: strcpy(dp->d_name, ".");
328: dp->d_namlen = 1;
329: } else if (ind == 1) {
330: strcpy(dp->d_name, "..");
331: dp->d_namlen = 2;
332: } else
333: panic("fdesc: ind is negative!");
334:
335: dp->d_reclen = UIO_MX;
336: dp->d_ino = 2;
337:
338: /*
339: * And ship to userland
340: */
341: error = uiomove((caddr_t) dp, UIO_MX, uio);
342: if (error)
343: break;
344:
345: ind++;
346: continue;
347: }
348: i = ind - 2;
349: if (i >= fdp->fd_nfiles) {
350: *eofflagp = 1;
351: break;
352: }
353: if (fdp->fd_ofiles[i] != NULL) {
354: struct direct d;
355: struct direct *dp = &d;
356: char *cp = dp->d_name;
357: #ifdef FDESC_FILEID
358: struct vattr va;
359: #endif
360: int j;
361:
362: bzero((caddr_t) dp, UIO_MX);
363:
364: /*
365: * Generate an ASCII representation of the name.
366: * This can cope with fds in the range 0..99999
367: */
368: cp++;
369: if (i > 10) cp++;
370: if (i > 100) cp++;
371: if (i > 1000) cp++;
372: if (i > 10000) cp++;
373: if (i > 100000) panic("fdesc_readdir");
374: dp->d_namlen = cp - dp->d_name;
375: *cp = '\0';
376: j = i;
377: do {
378: *--cp = j % 10 + '0';
379: j /= 10;
380: } while (j > 0);
381: /*
382: * Fill in the remaining fields
383: */
384: dp->d_reclen = UIO_MX;
385: dp->d_ino = i + 3;
386: #ifdef FDESC_FILEID
387: /*
388: * If we want the file ids to match the
389: * we must call getattr on the underlying file.
390: * fdesc_attr may return an error, in which case
391: * we ignore the returned file id.
392: */
393: error = fdesc_attr(i, &va, cred, p);
394: if (error == 0)
395: dp->d_ino = va.va_fileid;
396: #endif
397: /*
398: * And ship to userland
399: */
400: error = uiomove((caddr_t) dp, UIO_MX, uio);
401: if (error)
402: break;
403: }
404: ind++;
405: }
406:
407: uio->uio_offset = ind * UIO_MX;
408: return (error);
409: }
410:
411: fdesc_inactive(vp, p)
412: struct vnode *vp;
413: struct proc *p;
414: {
415: /*
416: * Clear out the v_type field to avoid
417: * nasty things happening in vgone().
418: */
419: vp->v_type = VNON;
420: #ifdef FDESC_DIAGNOSTIC
421: printf("fdesc_inactive(%x)\n", vp);
422: #endif
423: return (0);
424: }
425:
426: /*
427: * Print out the contents of a /dev/fd vnode.
428: */
429: /* ARGSUSED */
430: fdesc_print(vp)
431: struct vnode *vp;
432: {
433: printf("tag VT_NON, fdesc vnode\n");
434: }
435:
436: /*
437: * /dev/fd vnode unsupported operation
438: */
439: fdesc_enotsupp()
440: {
441: return (EOPNOTSUPP);
442: }
443:
444: /*
445: * /dev/fd "should never get here" operation
446: */
447: fdesc_badop()
448: {
449: panic("fdesc: bad op");
450: /* NOTREACHED */
451: }
452:
453: /*
454: * /dev/fd vnode null operation
455: */
456: fdesc_nullop()
457: {
458: return (0);
459: }
460:
461: #define fdesc_create ((int (*) __P(( \
462: struct nameidata *ndp, \
463: struct vattr *vap, \
464: struct proc *p))) fdesc_enotsupp)
465: #define fdesc_mknod ((int (*) __P(( \
466: struct nameidata *ndp, \
467: struct vattr *vap, \
468: struct ucred *cred, \
469: struct proc *p))) fdesc_enotsupp)
470: #define fdesc_close ((int (*) __P(( \
471: struct vnode *vp, \
472: int fflag, \
473: struct ucred *cred, \
474: struct proc *p))) nullop)
475: #define fdesc_access ((int (*) __P(( \
476: struct vnode *vp, \
477: int mode, \
478: struct ucred *cred, \
479: struct proc *p))) nullop)
480: #define fdesc_read ((int (*) __P(( \
481: struct vnode *vp, \
482: struct uio *uio, \
483: int ioflag, \
484: struct ucred *cred))) fdesc_enotsupp)
485: #define fdesc_write ((int (*) __P(( \
486: struct vnode *vp, \
487: struct uio *uio, \
488: int ioflag, \
489: struct ucred *cred))) fdesc_enotsupp)
490: #define fdesc_ioctl ((int (*) __P(( \
491: struct vnode *vp, \
492: int command, \
493: caddr_t data, \
494: int fflag, \
495: struct ucred *cred, \
496: struct proc *p))) fdesc_enotsupp)
497: #define fdesc_select ((int (*) __P(( \
498: struct vnode *vp, \
499: int which, \
500: int fflags, \
501: struct ucred *cred, \
502: struct proc *p))) fdesc_enotsupp)
503: #define fdesc_mmap ((int (*) __P(( \
504: struct vnode *vp, \
505: int fflags, \
506: struct ucred *cred, \
507: struct proc *p))) fdesc_enotsupp)
508: #define fdesc_fsync ((int (*) __P(( \
509: struct vnode *vp, \
510: int fflags, \
511: struct ucred *cred, \
512: int waitfor, \
513: struct proc *p))) nullop)
514: #define fdesc_seek ((int (*) __P(( \
515: struct vnode *vp, \
516: off_t oldoff, \
517: off_t newoff, \
518: struct ucred *cred))) nullop)
519: #define fdesc_remove ((int (*) __P(( \
520: struct nameidata *ndp, \
521: struct proc *p))) fdesc_enotsupp)
522: #define fdesc_link ((int (*) __P(( \
523: struct vnode *vp, \
524: struct nameidata *ndp, \
525: struct proc *p))) fdesc_enotsupp)
526: #define fdesc_rename ((int (*) __P(( \
527: struct nameidata *fndp, \
528: struct nameidata *tdnp, \
529: struct proc *p))) fdesc_enotsupp)
530: #define fdesc_mkdir ((int (*) __P(( \
531: struct nameidata *ndp, \
532: struct vattr *vap, \
533: struct proc *p))) fdesc_enotsupp)
534: #define fdesc_rmdir ((int (*) __P(( \
535: struct nameidata *ndp, \
536: struct proc *p))) fdesc_enotsupp)
537: #define fdesc_symlink ((int (*) __P(( \
538: struct nameidata *ndp, \
539: struct vattr *vap, \
540: char *target, \
541: struct proc *p))) fdesc_enotsupp)
542: #define fdesc_readlink ((int (*) __P(( \
543: struct vnode *vp, \
544: struct uio *uio, \
545: struct ucred *cred))) fdesc_enotsupp)
546: #define fdesc_abortop ((int (*) __P(( \
547: struct nameidata *ndp))) nullop)
548: #ifdef FDESC_DIAGNOSTIC
549: int fdesc_reclaim(vp)
550: struct vnode *vp;
551: {
552: printf("fdesc_reclaim(%x)\n", vp);
553: return (0);
554: }
555: #else
556: #define fdesc_reclaim ((int (*) __P(( \
557: struct vnode *vp))) nullop)
558: #endif
559: #define fdesc_lock ((int (*) __P(( \
560: struct vnode *vp))) nullop)
561: #define fdesc_unlock ((int (*) __P(( \
562: struct vnode *vp))) nullop)
563: #define fdesc_bmap ((int (*) __P(( \
564: struct vnode *vp, \
565: daddr_t bn, \
566: struct vnode **vpp, \
567: daddr_t *bnp))) fdesc_badop)
568: #define fdesc_strategy ((int (*) __P(( \
569: struct buf *bp))) fdesc_badop)
570: #define fdesc_islocked ((int (*) __P(( \
571: struct vnode *vp))) nullop)
572: #define fdesc_advlock ((int (*) __P(( \
573: struct vnode *vp, \
574: caddr_t id, \
575: int op, \
576: struct flock *fl, \
577: int flags))) fdesc_enotsupp)
578:
579: struct vnodeops fdesc_vnodeops = {
580: fdesc_lookup, /* lookup */
581: fdesc_create, /* create */
582: fdesc_mknod, /* mknod */
583: fdesc_open, /* open */
584: fdesc_close, /* close */
585: fdesc_access, /* access */
586: fdesc_getattr, /* getattr */
587: fdesc_setattr, /* setattr */
588: fdesc_read, /* read */
589: fdesc_write, /* write */
590: fdesc_ioctl, /* ioctl */
591: fdesc_select, /* select */
592: fdesc_mmap, /* mmap */
593: fdesc_fsync, /* fsync */
594: fdesc_seek, /* seek */
595: fdesc_remove, /* remove */
596: fdesc_link, /* link */
597: fdesc_rename, /* rename */
598: fdesc_mkdir, /* mkdir */
599: fdesc_rmdir, /* rmdir */
600: fdesc_symlink, /* symlink */
601: fdesc_readdir, /* readdir */
602: fdesc_readlink, /* readlink */
603: fdesc_abortop, /* abortop */
604: fdesc_inactive, /* inactive */
605: fdesc_reclaim, /* reclaim */
606: fdesc_lock, /* lock */
607: fdesc_unlock, /* unlock */
608: fdesc_bmap, /* bmap */
609: fdesc_strategy, /* strategy */
610: fdesc_print, /* print */
611: fdesc_islocked, /* islocked */
612: fdesc_advlock, /* advlock */
613: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.