|
|
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: kernfs_vnops.c,v 1.4 1993/03/27 00:37:11 cgd Exp $
37: */
38:
39: /*
40: * Kernel parameter filesystem
41: */
42:
43: #include "param.h"
44: #include "systm.h"
45: #include "kernel.h"
46: #include "types.h"
47: #include "time.h"
48: #include "proc.h"
49: #include "file.h"
50: #include "vnode.h"
51: #include "stat.h"
52: #include "mount.h"
53: #include "namei.h"
54: #include "buf.h"
55: #include "miscfs/kernfs/kernfs.h"
56:
57: #include "../ufs/dir.h" /* For readdir() XXX */
58:
59: #define KSTRING 256 /* Largest I/O available via this filesystem */
60: #define UIO_MX 32
61:
62: struct kern_target {
63: char *kt_name;
64: void *kt_data;
65: #define KTT_NULL 1
66: #define KTT_TIME 5
67: #define KTT_INT 17
68: #define KTT_STRING 31
69: #define KTT_HOSTNAME 47
70: #define KTT_AVENRUN 53
71: int kt_tag;
72: #define KTM_RO 0
73: #define KTM_RO_MODE (S_IRUSR|S_IRGRP|S_IROTH)
74: #define KTM_RW 43
75: #define KTM_RW_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
76: #define KTM_DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
77: int kt_rw;
78: int kt_vtype;
79: } kern_targets[] = {
80: /* NOTE: The name must be less than UIO_MX-16 chars in length */
81: /* name data tag ro/rw */
82: { ".", 0, KTT_NULL, KTM_RO, VDIR },
83: { "..", 0, KTT_NULL, KTM_RO, VDIR },
84: { "copyright", copyright, KTT_STRING, KTM_RO, VREG },
85: { "hostname", 0, KTT_HOSTNAME, KTM_RW, VREG },
86: { "hz", &hz, KTT_INT, KTM_RO, VREG },
87: { "loadavg", 0, KTT_AVENRUN, KTM_RO, VREG },
88: { "physmem", &physmem, KTT_INT, KTM_RO, VREG },
89: { "root", 0, KTT_NULL, KTM_RO, VDIR },
90: { "rootdev", 0, KTT_NULL, KTM_RO, VBLK },
91: { "rrootdev", 0, KTT_NULL, KTM_RO, VCHR },
92: { "time", 0, KTT_TIME, KTM_RO, VREG },
93: { "version", version, KTT_STRING, KTM_RO, VREG },
94: };
95:
96: static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
97:
98: static int
99: kernfs_xread(kt, buf, len, lenp)
100: struct kern_target *kt;
101: char *buf;
102: int len;
103: int *lenp;
104: {
105: int xlen;
106:
107: switch (kt->kt_tag) {
108: case KTT_TIME: {
109: struct timeval tv;
110: microtime(&tv);
111: sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
112: break;
113: }
114:
115: case KTT_INT: {
116: int *ip = kt->kt_data;
117: sprintf(buf, "%d\n", *ip);
118: break;
119: }
120:
121: case KTT_STRING: {
122: char *cp = kt->kt_data;
123: int xlen = strlen(cp) + 1;
124:
125: if (xlen >= len)
126: return (EINVAL);
127:
128: bcopy(cp, buf, xlen);
129: break;
130: }
131:
132: case KTT_HOSTNAME: {
133: char *cp = hostname;
134: int xlen = hostnamelen;
135:
136: if (xlen >= len)
137: return (EINVAL);
138:
139: sprintf(buf, "%s\n", cp);
140: break;
141: }
142:
143: case KTT_AVENRUN:
144: sprintf(buf, "%d %d %d %d\n",
145: averunnable[0],
146: averunnable[1],
147: averunnable[2],
148: FSCALE);
149: break;
150:
151: default:
152: return (EINVAL);
153: }
154:
155: *lenp = strlen(buf);
156: return (0);
157: }
158:
159: static int
160: kernfs_xwrite(kt, buf, len)
161: struct kern_target *kt;
162: char *buf;
163: int len;
164: {
165: switch (kt->kt_tag) {
166: case KTT_HOSTNAME: {
167: if (buf[len-1] == '\n')
168: --len;
169: bcopy(buf, hostname, len);
170: hostnamelen = len - 1;
171: return (0);
172: }
173:
174: default:
175: return (EIO);
176: }
177: }
178:
179: /*
180: * vp is the current namei directory
181: * ndp is the name to locate in that directory...
182: */
183: kernfs_lookup(dvp, ndp, p)
184: struct vnode *dvp;
185: struct nameidata *ndp;
186: struct proc *p;
187: {
188: char *pname = ndp->ni_ptr;
189: int error = ENOENT;
190: int i;
191: struct vnode *fvp;
192:
193: #ifdef KERNFS_DIAGNOSTIC
194: printf("kernfs_lookup(%s)\n", pname);
195: #endif
196: if (ndp->ni_namelen == 1 && *pname == '.') {
197: ndp->ni_dvp = dvp;
198: ndp->ni_vp = dvp;
199: VREF(dvp);
200: /*VOP_LOCK(dvp);*/
201: return (0);
202: }
203:
204: if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
205: ndp->ni_dvp = dvp;
206: ndp->ni_vp = rootdir;
207: VREF(rootdir);
208: VOP_LOCK(rootdir);
209: return (0);
210: }
211:
212: /*
213: * /kern/rootdev is the root device
214: */
215: if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
216: if (vfinddev(rootdev, VBLK, &fvp))
217: return (ENXIO);
218: ndp->ni_dvp = dvp;
219: ndp->ni_vp = fvp;
220: VREF(fvp);
221: VOP_LOCK(fvp);
222: return (0);
223: }
224:
225: /*
226: * /kern/rrootdev is the root device
227: */
228: if (ndp->ni_namelen == 8 && bcmp(pname, "rrootdev", 7) == 0) {
229: ndp->ni_dvp = dvp;
230: ndp->ni_vp = rrootdevvp;
231: VREF(rrootdevvp);
232: VOP_LOCK(rrootdevvp);
233: return (0);
234: }
235:
236: for (i = 0; i < nkern_targets; i++) {
237: struct kern_target *kt = &kern_targets[i];
238: if (ndp->ni_namelen == strlen(kt->kt_name) &&
239: bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
240: error = 0;
241: break;
242: }
243: }
244:
245: #ifdef KERNFS_DIAGNOSTIC
246: printf("kernfs_lookup: i = %d, error = %d\n", i, error);
247: #endif
248:
249: if (error)
250: goto bad;
251:
252: #ifdef KERNFS_DIAGNOSTIC
253: printf("kernfs_lookup: allocate new vnode\n");
254: #endif
255: error = getnewvnode(VT_UFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
256: if (error)
257: goto bad;
258: VTOKERN(fvp)->kf_kt = &kern_targets[i];
259: fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
260: ndp->ni_dvp = dvp;
261: ndp->ni_vp = fvp;
262: #ifdef KERNFS_DIAGNOSTIC
263: printf("kernfs_lookup: newvp = %x\n", fvp);
264: #endif
265: return (0);
266:
267: bad:;
268: ndp->ni_dvp = dvp;
269: ndp->ni_vp = NULL;
270: #ifdef KERNFS_DIAGNOSTIC
271: printf("kernfs_lookup: error = %d\n", error);
272: #endif
273: return (error);
274: }
275:
276: kernfs_open(vp, mode, cred, p)
277: struct vnode *vp;
278: int mode;
279: struct ucred *cred;
280: struct proc *p;
281: {
282: int error;
283: struct filedesc *fdp;
284: struct file *fp;
285: int dfd;
286: int fd;
287:
288: #ifdef KERNFS_DIAGNOSTIC
289: printf("kernfs_open\n");
290: #endif
291:
292: /*
293: * Can always open the root (modulo perms)
294: */
295: if (vp->v_flag & VROOT)
296: return (0);
297:
298: #ifdef KERNFS_DIAGNOSTIC
299: printf("kernfs_open, mode = %x, file = %s\n",
300: mode, VTOKERN(vp)->kf_kt->kt_name);
301: #endif
302:
303: if ((mode & FWRITE) && VTOKERN(vp)->kf_kt->kt_rw != KTM_RW)
304: return (EBADF);
305:
306: return (0);
307: }
308:
309: kernfs_getattr(vp, vap, cred, p)
310: struct vnode *vp;
311: struct vattr *vap;
312: struct ucred *cred;
313: struct proc *p;
314: {
315: int error = 0;
316: char strbuf[KSTRING];
317: struct kern_target *kt = VTOKERN(vp)->kf_kt;
318:
319: bzero((caddr_t) vap, sizeof(*vap));
320: vattr_null(vap);
321: vap->va_uid = 0;
322: vap->va_gid = 0;
323: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
324: /* vap->va_qsize = 0; */
325: vap->va_blocksize = DEV_BSIZE;
326: microtime(&vap->va_atime);
327: vap->va_mtime = vap->va_atime;
328: vap->va_ctime = vap->va_ctime;
329: vap->va_gen = 0;
330: vap->va_flags = 0;
331: vap->va_rdev = 0;
332: /* vap->va_qbytes = 0; */
333: vap->va_bytes = 0;
334:
335: if (vp->v_flag & VROOT) {
336: #ifdef KERNFS_DIAGNOSTIC
337: printf("kernfs_getattr: stat rootdir\n");
338: #endif
339: vap->va_type = VDIR;
340: vap->va_mode = KTM_DIR_MODE;
341: vap->va_nlink = 2;
342: vap->va_fileid = 2;
343: vap->va_size = DEV_BSIZE;
344: } else {
345: #ifdef KERNFS_DIAGNOSTIC
346: printf("kernfs_getattr: stat target %s\n", kt->kt_name);
347: #endif
348: vap->va_type = kt->kt_vtype;
349: vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
350: vap->va_nlink = 1;
351: vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
352: error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
353: }
354:
355: vp->v_type = vap->va_type;
356: #ifdef KERNFS_DIAGNOSTIC
357: printf("kernfs_getattr: return error %d\n", error);
358: #endif
359: return (error);
360: }
361:
362: kernfs_setattr(vp, vap, cred, p)
363: struct vnode *vp;
364: struct vattr *vap;
365: struct ucred *cred;
366: struct proc *p;
367: {
368:
369: /*
370: * Silently ignore attribute changes.
371: * This allows for open with truncate to have no
372: * effect until some data is written. I want to
373: * do it this way because all writes are atomic.
374: */
375: return (0);
376: }
377:
378: static int
379: kernfs_read(vp, uio, ioflag, cred)
380: struct vnode *vp;
381: struct uio *uio;
382: int ioflag;
383: struct ucred *cred;
384: {
385: struct kern_target *kt = VTOKERN(vp)->kf_kt;
386: char strbuf[KSTRING];
387: int off = uio->uio_offset;
388: int len = 0;
389: char *cp = strbuf;
390: int error;
391: #ifdef KERNFS_DIAGNOSTIC
392: printf("kern_read %s\n", kt->kt_name);
393: #endif
394:
395: error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
396: if (error)
397: return (error);
398: cp = strbuf + off;
399: len -= off;
400: return (uiomove(cp, len, uio));
401: }
402:
403: static int
404: kernfs_write(vp, uio, ioflag, cred)
405: struct vnode *vp;
406: struct uio *uio;
407: int ioflag;
408: struct ucred *cred;
409: {
410: struct kern_target *kt = VTOKERN(vp)->kf_kt;
411: char strbuf[KSTRING];
412: int len = uio->uio_resid;
413: char *cp = strbuf;
414: int xlen;
415: int error;
416:
417: if (uio->uio_offset != 0)
418: return (EINVAL);
419:
420: xlen = min(uio->uio_resid, KSTRING-1);
421: error = uiomove(strbuf, xlen, uio);
422: if (error)
423: return (error);
424:
425: if (uio->uio_resid != 0)
426: return (EIO);
427:
428: strbuf[xlen] = '\0';
429: return (kernfs_xwrite(kt, strbuf, xlen));
430: }
431:
432: kernfs_readdir(vp, uio, cred, eofflagp)
433: struct vnode *vp;
434: struct uio *uio;
435: struct ucred *cred;
436: int *eofflagp;
437: {
438: struct filedesc *fdp;
439: int i;
440: int error;
441:
442: i = uio->uio_offset / UIO_MX;
443: error = 0;
444: while (uio->uio_resid > 0) {
445: #ifdef KERNFS_DIAGNOSTIC
446: printf("kernfs_readdir: i = %d\n", i);
447: #endif
448: if (i >= nkern_targets) {
449: *eofflagp = 1;
450: break;
451: }
452: {
453: struct direct d;
454: struct direct *dp = &d;
455: struct kern_target *kt = &kern_targets[i];
456:
457: bzero((caddr_t) dp, UIO_MX);
458:
459: dp->d_namlen = strlen(kt->kt_name);
460: bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
461:
462: #ifdef KERNFS_DIAGNOSTIC
463: printf("kernfs_readdir: name = %s, len = %d\n",
464: dp->d_name, dp->d_namlen);
465: #endif
466: /*
467: * Fill in the remaining fields
468: */
469: dp->d_reclen = UIO_MX;
470: dp->d_ino = i + 3;
471: /*
472: * And ship to userland
473: */
474: error = uiomove((caddr_t) dp, UIO_MX, uio);
475: if (error)
476: break;
477: }
478: i++;
479: }
480:
481: uio->uio_offset = i * UIO_MX;
482:
483: return (error);
484: }
485:
486: kernfs_inactive(vp, p)
487: struct vnode *vp;
488: struct proc *p;
489: {
490: /*
491: * Clear out the v_type field to avoid
492: * nasty things happening in vgone().
493: */
494: vp->v_type = VNON;
495: #ifdef KERNFS_DIAGNOSTIC
496: printf("kernfs_inactive(%x)\n", vp);
497: #endif
498: return (0);
499: }
500:
501: /*
502: * Print out the contents of a kernfs vnode.
503: */
504: /* ARGSUSED */
505: kernfs_print(vp)
506: struct vnode *vp;
507: {
508: printf("tag VT_NON, kernfs vnode\n");
509: }
510:
511: /*
512: * kernfs vnode unsupported operation
513: */
514: kernfs_enotsupp()
515: {
516: return (EOPNOTSUPP);
517: }
518:
519: /*
520: * kernfs "should never get here" operation
521: */
522: kernfs_badop()
523: {
524: panic("kernfs: bad op");
525: /* NOTREACHED */
526: }
527:
528: /*
529: * kernfs vnode null operation
530: */
531: kernfs_nullop()
532: {
533: return (0);
534: }
535:
536: #define kernfs_create ((int (*) __P(( \
537: struct nameidata *ndp, \
538: struct vattr *vap, \
539: struct proc *p))) kernfs_enotsupp)
540: #define kernfs_mknod ((int (*) __P(( \
541: struct nameidata *ndp, \
542: struct vattr *vap, \
543: struct ucred *cred, \
544: struct proc *p))) kernfs_enotsupp)
545: #define kernfs_close ((int (*) __P(( \
546: struct vnode *vp, \
547: int fflag, \
548: struct ucred *cred, \
549: struct proc *p))) nullop)
550: #define kernfs_access ((int (*) __P(( \
551: struct vnode *vp, \
552: int mode, \
553: struct ucred *cred, \
554: struct proc *p))) nullop)
555: #define kernfs_ioctl ((int (*) __P(( \
556: struct vnode *vp, \
557: int command, \
558: caddr_t data, \
559: int fflag, \
560: struct ucred *cred, \
561: struct proc *p))) kernfs_enotsupp)
562: #define kernfs_select ((int (*) __P(( \
563: struct vnode *vp, \
564: int which, \
565: int fflags, \
566: struct ucred *cred, \
567: struct proc *p))) kernfs_enotsupp)
568: #define kernfs_mmap ((int (*) __P(( \
569: struct vnode *vp, \
570: int fflags, \
571: struct ucred *cred, \
572: struct proc *p))) kernfs_enotsupp)
573: #define kernfs_fsync ((int (*) __P(( \
574: struct vnode *vp, \
575: int fflags, \
576: struct ucred *cred, \
577: int waitfor, \
578: struct proc *p))) nullop)
579: #define kernfs_seek ((int (*) __P(( \
580: struct vnode *vp, \
581: off_t oldoff, \
582: off_t newoff, \
583: struct ucred *cred))) nullop)
584: #define kernfs_remove ((int (*) __P(( \
585: struct nameidata *ndp, \
586: struct proc *p))) kernfs_enotsupp)
587: #define kernfs_link ((int (*) __P(( \
588: struct vnode *vp, \
589: struct nameidata *ndp, \
590: struct proc *p))) kernfs_enotsupp)
591: #define kernfs_rename ((int (*) __P(( \
592: struct nameidata *fndp, \
593: struct nameidata *tdnp, \
594: struct proc *p))) kernfs_enotsupp)
595: #define kernfs_mkdir ((int (*) __P(( \
596: struct nameidata *ndp, \
597: struct vattr *vap, \
598: struct proc *p))) kernfs_enotsupp)
599: #define kernfs_rmdir ((int (*) __P(( \
600: struct nameidata *ndp, \
601: struct proc *p))) kernfs_enotsupp)
602: #define kernfs_symlink ((int (*) __P(( \
603: struct nameidata *ndp, \
604: struct vattr *vap, \
605: char *target, \
606: struct proc *p))) kernfs_enotsupp)
607: #define kernfs_readlink ((int (*) __P(( \
608: struct vnode *vp, \
609: struct uio *uio, \
610: struct ucred *cred))) kernfs_enotsupp)
611: #define kernfs_abortop ((int (*) __P(( \
612: struct nameidata *ndp))) nullop)
613: #ifdef KERNFS_DIAGNOSTIC
614: int kernfs_reclaim(vp)
615: struct vnode *vp;
616: {
617: printf("kernfs_reclaim(%x)\n", vp);
618: return (0);
619: }
620: #else
621: #define kernfs_reclaim ((int (*) __P(( \
622: struct vnode *vp))) nullop)
623: #endif
624: #define kernfs_lock ((int (*) __P(( \
625: struct vnode *vp))) nullop)
626: #define kernfs_unlock ((int (*) __P(( \
627: struct vnode *vp))) nullop)
628: #define kernfs_bmap ((int (*) __P(( \
629: struct vnode *vp, \
630: daddr_t bn, \
631: struct vnode **vpp, \
632: daddr_t *bnp))) kernfs_badop)
633: #define kernfs_strategy ((int (*) __P(( \
634: struct buf *bp))) kernfs_badop)
635: #define kernfs_islocked ((int (*) __P(( \
636: struct vnode *vp))) nullop)
637: #define kernfs_advlock ((int (*) __P(( \
638: struct vnode *vp, \
639: caddr_t id, \
640: int op, \
641: struct flock *fl, \
642: int flags))) kernfs_enotsupp)
643:
644: struct vnodeops kernfs_vnodeops = {
645: kernfs_lookup, /* lookup */
646: kernfs_create, /* create */
647: kernfs_mknod, /* mknod */
648: kernfs_open, /* open */
649: kernfs_close, /* close */
650: kernfs_access, /* access */
651: kernfs_getattr, /* getattr */
652: kernfs_setattr, /* setattr */
653: kernfs_read, /* read */
654: kernfs_write, /* write */
655: kernfs_ioctl, /* ioctl */
656: kernfs_select, /* select */
657: kernfs_mmap, /* mmap */
658: kernfs_fsync, /* fsync */
659: kernfs_seek, /* seek */
660: kernfs_remove, /* remove */
661: kernfs_link, /* link */
662: kernfs_rename, /* rename */
663: kernfs_mkdir, /* mkdir */
664: kernfs_rmdir, /* rmdir */
665: kernfs_symlink, /* symlink */
666: kernfs_readdir, /* readdir */
667: kernfs_readlink, /* readlink */
668: kernfs_abortop, /* abortop */
669: kernfs_inactive, /* inactive */
670: kernfs_reclaim, /* reclaim */
671: kernfs_lock, /* lock */
672: kernfs_unlock, /* unlock */
673: kernfs_bmap, /* bmap */
674: kernfs_strategy, /* strategy */
675: kernfs_print, /* print */
676: kernfs_islocked, /* islocked */
677: kernfs_advlock, /* advlock */
678: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.