Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/miscfs/kernfs/kernfs_vnops.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/miscfs/kernfs/kernfs_vnops.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.25 retrieving revision 1.39 diff -u -p -r1.25 -r1.39 --- src/sys/miscfs/kernfs/kernfs_vnops.c 1994/06/15 17:52:32 1.25 +++ src/sys/miscfs/kernfs/kernfs_vnops.c 1995/10/09 14:25:02 1.39 @@ -1,3 +1,5 @@ +/* $NetBSD: kernfs_vnops.c,v 1.39 1995/10/09 14:25:02 mycroft Exp $ */ + /* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -33,8 +35,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)kernfs_vnops.c 8.6 (Berkeley) 2/10/94 - * $Id: kernfs_vnops.c,v 1.25 1994/06/15 17:52:32 mycroft Exp $ + * @(#)kernfs_vnops.c 8.9 (Berkeley) 6/15/94 */ /* @@ -56,6 +57,7 @@ #include #include #include +#include #include #define KSTRING 256 /* Largest I/O available via this filesystem */ @@ -77,6 +79,7 @@ struct kern_target { #define KTT_HOSTNAME 47 #define KTT_AVENRUN 53 #define KTT_DEVICE 71 +#define KTT_MSGBUF 89 u_char kt_tag; u_char kt_vtype; mode_t kt_mode; @@ -91,6 +94,7 @@ struct kern_target { { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE }, { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE }, { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE }, + { DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE }, { DT_REG, N("pagesize"), &cnt.v_page_size, KTT_INT, VREG, READ_MODE }, { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE }, #if 0 @@ -104,39 +108,51 @@ struct kern_target { }; static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); -static int -kernfs_xread(kt, buf, len, lenp) +int +kernfs_xread(kt, off, bufp, len) struct kern_target *kt; - char *buf; + int off; + char **bufp; int len; - int *lenp; { switch (kt->kt_tag) { case KTT_TIME: { struct timeval tv; + microtime(&tv); - sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec); + sprintf(*bufp, "%d %d\n", tv.tv_sec, tv.tv_usec); break; } case KTT_INT: { int *ip = kt->kt_data; - sprintf(buf, "%d\n", *ip); + + sprintf(*bufp, "%d\n", *ip); break; } case KTT_STRING: { char *cp = kt->kt_data; - int xlen = strlen(cp) + 1; - - if (xlen >= len) - return (EINVAL); - bcopy(cp, buf, xlen); + *bufp = cp; break; } + case KTT_MSGBUF: { + extern struct msgbuf *msgbufp; + long n; + + if (off >= MSG_BSIZE) + return (0); + n = msgbufp->msg_bufx + off; + if (n >= MSG_BSIZE) + n -= MSG_BSIZE; + len = min(MSG_BSIZE - n, MSG_BSIZE - off); + *bufp = msgbufp->msg_bufc + n; + return (len); + } + case KTT_HOSTNAME: { char *cp = hostname; int xlen = hostnamelen; @@ -144,27 +160,31 @@ kernfs_xread(kt, buf, len, lenp) if (xlen >= (len-2)) return (EINVAL); - bcopy(cp, buf, xlen); - buf[xlen] = '\n'; - buf[xlen+1] = '\0'; + bcopy(cp, *bufp, xlen); + (*bufp)[xlen] = '\n'; + (*bufp)[xlen+1] = '\0'; break; } case KTT_AVENRUN: - sprintf(buf, "%ld %ld %ld %ld\n", + averunnable.fscale = FSCALE; + sprintf(*bufp, "%ld %ld %ld %ld\n", averunnable.ldavg[0], averunnable.ldavg[1], averunnable.ldavg[2], averunnable.fscale); break; default: - return (EIO); + return (0); } - *lenp = strlen(buf); - return (0); + len = strlen(*bufp); + if (len <= off) + return (0); + *bufp += off; + return (len - off); } -static int +int kernfs_xwrite(kt, buf, len) struct kern_target *kt; char *buf; @@ -211,6 +231,11 @@ kernfs_lookup(ap) printf("kernfs_lookup(%s)\n", pname); #endif + *vpp = NULLVP; + + if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) + return (EROFS); + if (cnp->cn_namelen == 1 && *pname == '.') { *vpp = dvp; VREF(dvp); @@ -227,24 +252,19 @@ kernfs_lookup(ap) } #endif - *vpp = NULL; - - for (error = ENOENT, kt = kern_targets, i = 0; i < nkern_targets; - kt++, i++) { - if (cnp->cn_namelen == strlen(kt->kt_name) && - bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) { - error = 0; - break; - } + for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) { + if (cnp->cn_namelen == kt->kt_namlen && + bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) + goto found; } #ifdef KERNFS_DIAGNOSTIC - printf("kernfs_lookup: i = %d, error = %d\n", i, error); + printf("kernfs_lookup: i = %d, failed", i); #endif - if (error) - return (error); + return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); +found: if (kt->kt_tag == KTT_DEVICE) { dev_t *dp = kt->kt_data; loop: @@ -288,52 +308,20 @@ kernfs_open(ap) return (0); } -static int +int kernfs_access(ap) struct vop_access_args /* { struct vnode *a_vp; - int a_mode; + int a_mode; struct ucred *a_cred; struct proc *a_p; } */ *ap; { - register struct vnode *vp = ap->a_vp; - register struct ucred *cred = ap->a_cred; - mode_t amode = ap->a_mode; + struct vnode *vp = ap->a_vp; mode_t fmode = (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode; - mode_t mask = 0; - register gid_t *gp; - int i; - - /* Some files are simply not modifiable. */ - if ((amode & VWRITE) && (fmode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0) - return (EPERM); - - /* Root can do anything else. */ - if (cred->cr_uid == 0) - return (0); - - /* Check for group 0 (wheel) permissions. */ - for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) - if (*gp == 0) { - if (amode & VEXEC) - mask |= S_IXGRP; - if (amode & VREAD) - mask |= S_IRGRP; - if (amode & VWRITE) - mask |= S_IWGRP; - return ((fmode & mask) == mask ? 0 : EACCES); - } - /* Otherwise, check everyone else. */ - if (amode & VEXEC) - mask |= S_IXOTH; - if (amode & VREAD) - mask |= S_IROTH; - if (amode & VWRITE) - mask |= S_IWOTH; - return ((fmode & mask) == mask ? 0 : EACCES); + return (vaccess(fmode, (uid_t)0, (gid_t)0, ap->a_mode, ap->a_cred)); } kernfs_getattr(ap) @@ -346,8 +334,9 @@ kernfs_getattr(ap) { struct vnode *vp = ap->a_vp; struct vattr *vap = ap->a_vap; + struct timeval tv; int error = 0; - char strbuf[KSTRING]; + char strbuf[KSTRING], *buf; bzero((caddr_t) vap, sizeof(*vap)); vattr_null(vap); @@ -356,7 +345,8 @@ kernfs_getattr(ap) vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; vap->va_size = 0; vap->va_blocksize = DEV_BSIZE; - microtime(&vap->va_atime); + microtime(&tv); + TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime); vap->va_mtime = vap->va_atime; vap->va_ctime = vap->va_ctime; vap->va_gen = 0; @@ -375,16 +365,19 @@ kernfs_getattr(ap) vap->va_size = DEV_BSIZE; } else { struct kern_target *kt = VTOKERN(vp)->kf_kt; - int nbytes; + int nbytes, total; #ifdef KERNFS_DIAGNOSTIC printf("kernfs_getattr: stat target %s\n", kt->kt_name); #endif vap->va_type = kt->kt_vtype; vap->va_mode = kt->kt_mode; vap->va_nlink = 1; - vap->va_fileid = 1 + (kt - kern_targets) / sizeof(*kt); - error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes); - vap->va_size = nbytes; + vap->va_fileid = 3 + (kt - kern_targets); + total = 0; + while (buf = strbuf, + nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf))) + total += nbytes; + vap->va_size = total; } #ifdef KERNFS_DIAGNOSTIC @@ -411,7 +404,7 @@ kernfs_setattr(ap) return (0); } -static int +int kernfs_read(ap) struct vop_read_args /* { struct vnode *a_vp; @@ -423,10 +416,9 @@ kernfs_read(ap) struct vnode *vp = ap->a_vp; struct uio *uio = ap->a_uio; struct kern_target *kt; - char strbuf[KSTRING]; - int off = uio->uio_offset; - int error, len; - char *cp; + char strbuf[KSTRING], *buf; + int off, len; + int error; if (vp->v_type == VDIR) return (EOPNOTSUPP); @@ -437,15 +429,21 @@ kernfs_read(ap) printf("kern_read %s\n", kt->kt_name); #endif - len = 0; - if (error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len)) - return (error); - if (len <= off) - return (0); - return (uiomove(&strbuf[off], len - off, uio)); + off = uio->uio_offset; +#if 0 + while (buf = strbuf, +#else + if (buf = strbuf, +#endif + len = kernfs_xread(kt, off, &buf, sizeof(strbuf))) { + if (error = uiomove(buf, len, uio)) + return (error); + off += len; + } + return (0); } -static int +int kernfs_write(ap) struct vop_write_args /* { struct vnode *a_vp; @@ -485,53 +483,58 @@ kernfs_readdir(ap) struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; + int *a_eofflag; + u_long *a_cookies; + int a_ncookies; } */ *ap; { struct uio *uio = ap->a_uio; - register struct kern_target *kt; struct dirent d; + struct kern_target *kt; int i; int error; + u_long *cookies = ap->a_cookies; + int ncookies = ap->a_ncookies; if (ap->a_vp->v_type != VDIR) return (ENOTDIR); - i = uio->uio_offset / UIO_MX; + if (uio->uio_resid < UIO_MX) + return (EINVAL); + if (uio->uio_offset < 0) + return (EINVAL); + error = 0; + i = uio->uio_offset; + bzero((caddr_t)&d, UIO_MX); + d.d_reclen = UIO_MX; + for (kt = &kern_targets[i]; uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) { - register struct dirent *dp = &d; #ifdef KERNFS_DIAGNOSTIC printf("kernfs_readdir: i = %d\n", i); #endif + if (kt->kt_tag == KTT_DEVICE) { - register dev_t *dp = kt->kt_data; + dev_t *dp = kt->kt_data; struct vnode *fvp; + if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) continue; } - bzero((caddr_t)dp, UIO_MX); - dp->d_namlen = kt->kt_namlen; - bcopy(kt->kt_name, dp->d_name, kt->kt_namlen + 1); -#ifdef KERNFS_DIAGNOSTIC - printf("kernfs_readdir: name = %s, len = %d\n", - dp->d_name, dp->d_namlen); -#endif - /* - * Fill in the remaining fields - */ - dp->d_reclen = UIO_MX; - dp->d_fileno = i + 3; - dp->d_type = kt->kt_type; - /* - * And ship to userland - */ - if (error = uiomove((caddr_t)dp, UIO_MX, uio)) + + d.d_fileno = i + 3; + d.d_namlen = kt->kt_namlen; + bcopy(kt->kt_name, d.d_name, kt->kt_namlen + 1); + d.d_type = kt->kt_type; + + if (error = uiomove((caddr_t)&d, UIO_MX, uio)) break; + if (ncookies-- > 0) + *cookies++ = i + 1; } - uio->uio_offset = i * UIO_MX; - + uio->uio_offset = i; return (error); } @@ -577,7 +580,7 @@ kernfs_pathconf(ap) struct vop_pathconf_args /* { struct vnode *a_vp; int a_name; - int *a_retval; + register_t *a_retval; } */ *ap; {