diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c index e91791a3c714..239a2c8aa0ef 100644 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ b/sys/fs/ntfs/ntfs_vfsops.c @@ -1,793 +1,793 @@ /* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */ /*- * Copyright (c) 1998, 1999 Semen Ustimenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*#define NTFS_DEBUG 1*/ #include #include #include #include #include #include MALLOC_DEFINE(M_NTFSMNT, "NTFS mount", "NTFS mount structure"); MALLOC_DEFINE(M_NTFSNTNODE,"NTFS ntnode", "NTFS ntnode information"); MALLOC_DEFINE(M_NTFSFNODE,"NTFS fnode", "NTFS fnode information"); MALLOC_DEFINE(M_NTFSDIR,"NTFS dir", "NTFS dir buffer"); struct sockaddr; static int ntfs_root(struct mount *, struct vnode **); static int ntfs_statfs(struct mount *, struct statfs *, struct thread *); static int ntfs_unmount(struct mount *, int, struct thread *); static int ntfs_vget(struct mount *mp, ino_t ino, int lkflags, struct vnode **vpp); static int ntfs_mountfs(register struct vnode *, struct mount *, struct ntfs_args *, struct thread *); static int ntfs_vptofh(struct vnode *, struct fid *); static int ntfs_fhtovp(struct mount *, struct fid *, struct vnode **); static int ntfs_mount(struct mount *, char *, caddr_t, struct nameidata *, struct thread *); static int ntfs_init(struct vfsconf *); static int ntfs_init ( struct vfsconf *vcp ) { ntfs_nthashinit(); ntfs_toupper_init(); return 0; } static int ntfs_uninit ( struct vfsconf *vcp ) { ntfs_toupper_destroy(); ntfs_nthashdestroy(); return 0; } static int ntfs_mount ( struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct thread *td ) { size_t size; int err = 0; struct vnode *devvp; struct ntfs_args args; /* * Use NULL path to flag a root mount */ if( path == NULL) { /* *** * Mounting root filesystem *** */ /* Get vnode for root device*/ if( bdevvp( rootdev, &rootvp)) panic("ntfs_mountroot: can't setup bdevvp for root"); /* * FS specific handling */ mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/ /* * Attempt mount */ if( ( err = ntfs_mountfs(rootvp, mp, &args, td)) != 0) { /* fs specific cleanup (if any)*/ goto error_1; } goto dostatfs; /* success*/ } /* *** * Mounting non-root filesystem or updating a filesystem *** */ /* copy in user arguments*/ err = copyin(data, (caddr_t)&args, sizeof (struct ntfs_args)); if (err) goto error_1; /* can't get arguments*/ /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { /* if not updating name...*/ if (args.fspec == 0) { /* * Process export requests. Jumping to "success" * will return the vfs_export() error code. */ err = vfs_export(mp, &args.export); goto success; } printf("ntfs_mount(): MNT_UPDATE not supported\n"); err = EINVAL; goto error_1; } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, td); err = namei(ndp); if (err) { /* can't get devvp!*/ goto error_1; } NDFREE(ndp, NDF_ONLY_PNBUF); devvp = ndp->ni_vp; if (!vn_isdisk(devvp, &err)) goto error_2; if (mp->mnt_flag & MNT_UPDATE) { #if 0 /* ******************** * UPDATE ******************** */ if (devvp != ntmp->um_devvp) err = EINVAL; /* needs translation */ else vrele(devvp); /* * Update device name only on success */ if( !err) { /* Save "mounted from" info for mount point (NULL pad)*/ copyinstr( args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); } #endif } else { /* ******************** * NEW MOUNT ******************** */ /* * Since this is a new mount, we want the names for * the device and the mount point copied in. If an * error occurs, the mountpoint is discarded by the * upper level code. Note that vfs_mount() handles * copying the mountpoint f_mntonname for us, so we * don't have to do it here unless we want to set it * to something other than "path" for some rason. */ /* Save "mounted from" info for mount point (NULL pad)*/ copyinstr( args.fspec, /* device name*/ mp->mnt_stat.f_mntfromname, /* save area*/ MNAMELEN - 1, /* max size*/ &size); /* real size*/ bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); err = ntfs_mountfs(devvp, mp, &args, td); } if (err) { goto error_2; } dostatfs: /* * Initialize FS stat information in mount struct; uses both * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname * * This code is common to root and non-root mounts */ (void)VFS_STATFS(mp, &mp->mnt_stat, td); goto success; error_2: /* error with devvp held*/ /* release devvp before failing*/ vrele(devvp); error_1: /* no state to back out*/ success: return(err); } /* * Common code for mount and mountroot */ int ntfs_mountfs(devvp, mp, argsp, td) register struct vnode *devvp; struct mount *mp; struct ntfs_args *argsp; struct thread *td; { struct buf *bp; struct ntfsmount *ntmp; dev_t dev = devvp->v_rdev; int error, ronly, ncount, i; struct vnode *vp; /* * Disallow multiple mounts of the same device. * Disallow mounting of a device that is currently in use * (except for root, which might share swap device for miniroot). * Flush out any old buffers remaining from a previous use. */ error = vfs_mountedon(devvp); if (error) return (error); ncount = vcount(devvp); if (devvp->v_object) ncount -= 1; if (ncount > 1 && devvp != rootvp) return (EBUSY); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = vinvalbuf(devvp, V_SAVE, td->td_ucred, td, 0, 0); VOP_UNLOCK(devvp, 0, td); if (error) return (error); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, td); VOP_UNLOCK(devvp, 0, td); if (error) return (error); bp = NULL; error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp); if (error) goto out; ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO); bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) ); brelse( bp ); bp = NULL; if (strncmp(ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) { error = EINVAL; dprintf(("ntfs_mountfs: invalid boot block\n")); goto out; } { int8_t cpr = ntmp->ntm_mftrecsz; if( cpr > 0 ) ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr; else ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps; } dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n", ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media, ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec)); dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n", (u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn)); ntmp->ntm_mountp = mp; ntmp->ntm_dev = dev; ntmp->ntm_devvp = devvp; ntmp->ntm_uid = argsp->uid; ntmp->ntm_gid = argsp->gid; ntmp->ntm_mode = argsp->mode; ntmp->ntm_flag = argsp->flag; /* Copy in the 8-bit to Unicode conversion table */ if (argsp->flag & NTFSMNT_U2WTABLE) { ntfs_82u_init(ntmp, argsp->u2w); } else { ntfs_82u_init(ntmp, NULL); } /* Initialize Unicode to 8-bit table from 8toU table */ ntfs_u28_init(ntmp, ntmp->ntm_82u); mp->mnt_data = (qaddr_t)ntmp; dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n", (ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.", (ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"", ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode)); /* * We read in some system nodes to do not allow * reclaim them and to have everytime access to them. */ { int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO }; for (i=0; i<3; i++) { error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE, &(ntmp->ntm_sysvn[pi[i]])); if(error) goto out1; ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM; VREF(ntmp->ntm_sysvn[pi[i]]); vput(ntmp->ntm_sysvn[pi[i]]); } } /* read the Unicode lowercase --> uppercase translation table, * if necessary */ if ((error = ntfs_toupper_use(mp, ntmp))) goto out1; /* * Scan $BitMap and count free clusters */ error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree); if(error) goto out1; /* * Read and translate to internal format attribute * definition file. */ { int num,j; struct attrdef ad; /* Open $AttrDef */ error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp ); if(error) goto out1; /* Count valid entries */ for(num=0;;num++) { error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, num * sizeof(ad), sizeof(ad), &ad, NULL); if (error) goto out1; if (ad.ad_name[0] == 0) break; } /* Alloc memory for attribute definitions */ MALLOC(ntmp->ntm_ad, struct ntvattrdef *, num * sizeof(struct ntvattrdef), M_NTFSMNT, M_WAITOK); ntmp->ntm_adnum = num; /* Read them and translate */ for(i=0;intm_ad[i].ad_name[j] = ad.ad_name[j]; } while(ad.ad_name[j++]); ntmp->ntm_ad[i].ad_namelen = j - 1; ntmp->ntm_ad[i].ad_type = ad.ad_type; } vput(vp); } mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; mp->mnt_maxsymlinklen = 0; mp->mnt_flag |= MNT_LOCAL; devvp->v_rdev->si_mountpoint = mp; return (0); out1: for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); if (vflush(mp, 0, 0)) dprintf(("ntfs_mountfs: vflush failed\n")); out: devvp->v_rdev->si_mountpoint = NULL; if (bp) brelse(bp); (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, td); return (error); } static int ntfs_unmount( struct mount *mp, int mntflags, struct thread *td) { register struct ntfsmount *ntmp; int error, ronly = 0, flags, i; dprintf(("ntfs_unmount: unmounting...\n")); ntmp = VFSTONTFS(mp); flags = 0; if(mntflags & MNT_FORCE) flags |= FORCECLOSE; dprintf(("ntfs_unmount: vflushing...\n")); error = vflush(mp, 0, flags | SKIPSYSTEM); if (error) { printf("ntfs_unmount: vflush failed: %d\n",error); return (error); } /* Check if only system vnodes are rest */ for(i=0;intm_sysvn[i]) && (vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY); /* Dereference all system vnodes */ for(i=0;intm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); /* vflush system vnodes */ error = vflush(mp, 0, flags); if (error) printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); /* Check if the type of device node isn't VBAD before - * touching v_specinfo. If the device vnode is revoked, the + * touching v_cdev. If the device vnode is revoked, the * field is NULL and touching it causes null pointer derefercence. */ if (ntmp->ntm_devvp->v_type != VBAD) ntmp->ntm_devvp->v_rdev->si_mountpoint = NULL; vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, td, 0, 0); error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, td); vrele(ntmp->ntm_devvp); /* free the toupper table, if this has been last mounted ntfs volume */ ntfs_toupper_unuse(); dprintf(("ntfs_umount: freeing memory...\n")); ntfs_u28_uninit(ntmp); ntfs_82u_uninit(ntmp); mp->mnt_data = (qaddr_t)0; mp->mnt_flag &= ~MNT_LOCAL; FREE(ntmp->ntm_ad, M_NTFSMNT); FREE(ntmp, M_NTFSMNT); return (error); } static int ntfs_root( struct mount *mp, struct vnode **vpp ) { struct vnode *nvp; int error = 0; dprintf(("ntfs_root(): sysvn: %p\n", VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO])); error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp); if(error) { printf("ntfs_root: VFS_VGET failed: %d\n",error); return (error); } *vpp = nvp; return (0); } int ntfs_calccfree( struct ntfsmount *ntmp, cn_t *cfreep) { struct vnode *vp; u_int8_t *tmp; int j, error; long cfree = 0; size_t bmsize, i; vp = ntmp->ntm_sysvn[NTFS_BITMAPINO]; bmsize = VTOF(vp)->f_size; MALLOC(tmp, u_int8_t *, bmsize, M_TEMP, M_WAITOK); error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL, 0, bmsize, tmp, NULL); if (error) goto out; for(i=0;intm_sysvn[NTFS_MFTINO])->f_size; mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated; sbp->f_type = mp->mnt_vfc->vfc_typenum; sbp->f_bsize = ntmp->ntm_bps; sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc; sbp->f_blocks = ntmp->ntm_bootfile.bf_spv; sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree); sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec; sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) + sbp->f_ffree; if (sbp != &mp->mnt_stat) { bcopy((caddr_t)mp->mnt_stat.f_mntonname, (caddr_t)&sbp->f_mntonname[0], MNAMELEN); bcopy((caddr_t)mp->mnt_stat.f_mntfromname, (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); } sbp->f_flags = mp->mnt_flag; return (0); } /*ARGSUSED*/ static int ntfs_fhtovp( struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct vnode *nvp; struct ntfid *ntfhp = (struct ntfid *)fhp; int error; ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino)); if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) { *vpp = NULLVP; return (error); } /* XXX as unlink/rmdir/mkdir/creat are not currently possible * with NTFS, we don't need to check anything else for now */ *vpp = nvp; return (0); } static int ntfs_vptofh( struct vnode *vp, struct fid *fhp) { register struct ntnode *ntp; register struct ntfid *ntfhp; ddprintf(("ntfs_fhtovp(): %p\n", vp)); ntp = VTONT(vp); ntfhp = (struct ntfid *)fhp; ntfhp->ntfid_len = sizeof(struct ntfid); ntfhp->ntfid_ino = ntp->i_number; /* ntfhp->ntfid_gen = ntp->i_gen; */ return (0); } int ntfs_vgetex( struct mount *mp, ino_t ino, u_int32_t attrtype, char *attrname, u_long lkflags, u_long flags, struct thread *td, struct vnode **vpp) { int error; register struct ntfsmount *ntmp; struct ntnode *ip; struct fnode *fp; struct vnode *vp; enum vtype f_type; dprintf(("ntfs_vgetex: ino: %d, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n", ino, attrtype, attrname?attrname:"", (u_long)lkflags, (u_long)flags )); ntmp = VFSTONTFS(mp); *vpp = NULL; /* Get ntnode */ error = ntfs_ntlookup(ntmp, ino, &ip); if (error) { printf("ntfs_vget: ntfs_ntget failed\n"); return (error); } /* It may be not initialized fully, so force load it */ if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) { error = ntfs_loadntnode(ntmp, ip); if(error) { printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %d\n", ip->i_number); ntfs_ntput(ip); return (error); } } error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); if (error) { printf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntput(ip); return (error); } f_type = VNON; if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) { if ((ip->i_frflag & NTFS_FRFLAG_DIR) && (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) { f_type = VDIR; } else if (flags & VG_EXT) { f_type = VNON; fp->f_size = fp->f_allocated = 0; } else { f_type = VREG; error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated); if (error) { ntfs_ntput(ip); return (error); } } fp->f_flag |= FN_VALID; } if (FTOV(fp)) { vget(FTOV(fp), lkflags, td); *vpp = FTOV(fp); ntfs_ntput(ip); return (0); } error = getnewvnode("ntfs", ntmp->ntm_mountp, ntfs_vnodeop_p, &vp); if(error) { ntfs_frele(fp); ntfs_ntput(ip); return (error); } dprintf(("ntfs_vget: vnode: %p for ntnode: %d\n", vp,ino)); lockinit(&fp->f_lock, PINOD, "fnode", VLKTIMEOUT, 0); fp->f_vp = vp; vp->v_data = fp; vp->v_type = f_type; if (ino == NTFS_ROOTINO) vp->v_vflag |= VV_ROOT; ntfs_ntput(ip); if (lkflags & LK_TYPE_MASK) { error = vn_lock(vp, lkflags, td); if (error) { vput(vp); return (error); } } *vpp = vp; return (0); } static int ntfs_vget( struct mount *mp, ino_t ino, int lkflags, struct vnode **vpp) { return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0, curthread, vpp); } static struct vfsops ntfs_vfsops = { ntfs_mount, vfs_stdstart, ntfs_unmount, ntfs_root, vfs_stdquotactl, ntfs_statfs, vfs_stdsync, ntfs_vget, ntfs_fhtovp, vfs_stdcheckexp, ntfs_vptofh, ntfs_init, ntfs_uninit, vfs_stdextattrctl, }; VFS_SET(ntfs_vfsops, ntfs, 0); diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index 1fbe8130622b..05fc62b177ec 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -1,484 +1,484 @@ /*- * Copyright (c) 1999-2002 Poul-Henning Kamp * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define cdevsw_ALLOCSTART (NUMCDEVSW/2) static struct cdevsw *cdevsw[NUMCDEVSW]; static MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); /* * This is the number of hash-buckets. Experiements with 'real-life' * udev_t's show that a prime halfway between two powers of two works * best. */ #define DEVT_HASH 83 /* The number of dev_t's we can create before malloc(9) kick in. */ #define DEVT_STASH 50 -static struct specinfo devt_stash[DEVT_STASH]; +static struct cdev devt_stash[DEVT_STASH]; -static LIST_HEAD(, specinfo) dev_hash[DEVT_HASH]; +static LIST_HEAD(, cdev) dev_hash[DEVT_HASH]; -static LIST_HEAD(, specinfo) dev_free; +static LIST_HEAD(, cdev) dev_free; devfs_create_t *devfs_create_hook; devfs_destroy_t *devfs_destroy_hook; int devfs_present; static int ready_for_devs; static int free_devt; SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, ""); /* XXX: This is a hack */ void disk_dev_synth(dev_t dev); struct cdevsw * devsw(dev_t dev) { if (dev->si_devsw) return (dev->si_devsw); /* XXX: Hack around our backwards disk code */ disk_dev_synth(dev); if (dev->si_devsw) return (dev->si_devsw); if (devfs_present) return (NULL); return(cdevsw[major(dev)]); } /* * Add a cdevsw entry */ int cdevsw_add(struct cdevsw *newentry) { if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", newentry->d_name, newentry->d_maj); return (EINVAL); } if (cdevsw[newentry->d_maj]) { printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", newentry->d_name, cdevsw[newentry->d_maj]->d_name); } cdevsw[newentry->d_maj] = newentry; return (0); } /* * Remove a cdevsw entry */ int cdevsw_remove(struct cdevsw *oldentry) { if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", oldentry->d_name, oldentry->d_maj); return EINVAL; } cdevsw[oldentry->d_maj] = NULL; return 0; } /* * dev_t and u_dev_t primitives */ int major(dev_t x) { if (x == NODEV) return NOUDEV; return((x->si_udev >> 8) & 0xff); } int minor(dev_t x) { if (x == NODEV) return NOUDEV; return(x->si_udev & 0xffff00ff); } int dev2unit(dev_t x) { int i; if (x == NODEV) return NOUDEV; i = minor(x); return ((i & 0xff) | (i >> 8)); } int unit2minor(int unit) { KASSERT(unit <= 0xffffff, ("Invalid unit (%d) in unit2minor", unit)); return ((unit & 0xff) | ((unit << 8) & ~0xffff)); } static dev_t allocdev(void) { static int stashed; - struct specinfo *si; + struct cdev *si; if (LIST_FIRST(&dev_free)) { si = LIST_FIRST(&dev_free); LIST_REMOVE(si, si_hash); } else if (stashed >= DEVT_STASH) { - MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, + MALLOC(si, struct cdev *, sizeof(*si), M_DEVT, M_USE_RESERVE | M_ZERO); } else { si = devt_stash + stashed++; bzero(si, sizeof *si); si->si_flags |= SI_STASHED; } LIST_INIT(&si->si_children); TAILQ_INIT(&si->si_snapshots); return (si); } dev_t makedev(int x, int y) { - struct specinfo *si; + struct cdev *si; udev_t udev; int hash; if (x == umajor(NOUDEV) && y == uminor(NOUDEV)) panic("makedev of NOUDEV"); udev = (x << 8) | y; hash = udev % DEVT_HASH; LIST_FOREACH(si, &dev_hash[hash], si_hash) { if (si->si_udev == udev) return (si); } si = allocdev(); si->si_udev = udev; LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); return (si); } void freedev(dev_t dev) { if (!free_devt) return; if (SLIST_FIRST(&dev->si_hlist)) return; if (dev->si_devsw || dev->si_drv1 || dev->si_drv2) return; LIST_REMOVE(dev, si_hash); if (dev->si_flags & SI_STASHED) { bzero(dev, sizeof(*dev)); dev->si_flags |= SI_STASHED; LIST_INSERT_HEAD(&dev_free, dev, si_hash); } else { FREE(dev, M_DEVT); } } udev_t dev2udev(dev_t x) { if (x == NODEV) return NOUDEV; return (x->si_udev); } dev_t udev2dev(udev_t x, int b) { if (x == NOUDEV) return (NODEV); switch (b) { case 0: return makedev(umajor(x), uminor(x)); case 1: return (NODEV); default: Debugger("udev2dev(...,X)"); return NODEV; } } int uminor(udev_t dev) { return(dev & 0xffff00ff); } int umajor(udev_t dev) { return((dev & 0xff00) >> 8); } udev_t makeudev(int x, int y) { return ((x << 8) | y); } dev_t make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, const char *fmt, ...) { dev_t dev; va_list ap; int i; KASSERT(umajor(makeudev(devsw->d_maj, minor)) == devsw->d_maj, ("Invalid minor (%d) in make_dev", minor)); if (!ready_for_devs) { printf("WARNING: Driver mistake: make_dev(%s) called before SI_SUB_DRIVERS\n", fmt); /* XXX panic here once drivers are cleaned up */ } dev = makedev(devsw->d_maj, minor); if (dev->si_flags & SI_NAMED) { printf( "WARNING: Driver mistake: repeat make_dev(\"%s\")\n", dev->si_name); panic("don't do that"); return (dev); } va_start(ap, fmt); i = kvprintf(fmt, NULL, dev->si_name, 32, ap); dev->si_name[i] = '\0'; va_end(ap); dev->si_devsw = devsw; dev->si_uid = uid; dev->si_gid = gid; dev->si_mode = perms; dev->si_flags |= SI_NAMED; if (devfs_create_hook) devfs_create_hook(dev); return (dev); } int dev_named(dev_t pdev, const char *name) { dev_t cdev; if (strcmp(devtoname(pdev), name) == 0) return (1); LIST_FOREACH(cdev, &pdev->si_children, si_siblings) if (strcmp(devtoname(cdev), name) == 0) return (1); return (0); } void dev_depends(dev_t pdev, dev_t cdev) { cdev->si_parent = pdev; cdev->si_flags |= SI_CHILD; LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings); } dev_t make_dev_alias(dev_t pdev, const char *fmt, ...) { dev_t dev; va_list ap; int i; dev = allocdev(); dev->si_flags |= SI_ALIAS; dev->si_flags |= SI_NAMED; dev_depends(pdev, dev); va_start(ap, fmt); i = kvprintf(fmt, NULL, dev->si_name, 32, ap); dev->si_name[i] = '\0'; va_end(ap); if (devfs_create_hook) devfs_create_hook(dev); return (dev); } void revoke_and_destroy_dev(dev_t dev) { struct vnode *vp; GIANT_REQUIRED; vp = SLIST_FIRST(&dev->si_hlist); if (vp != NULL) VOP_REVOKE(vp, REVOKEALL); destroy_dev(dev); } void destroy_dev(dev_t dev) { if (!(dev->si_flags & SI_NAMED)) { printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n", major(dev), minor(dev)); panic("don't do that"); return; } if (devfs_destroy_hook) devfs_destroy_hook(dev); if (dev->si_flags & SI_CHILD) { LIST_REMOVE(dev, si_siblings); dev->si_flags &= ~SI_CHILD; } while (!LIST_EMPTY(&dev->si_children)) destroy_dev(LIST_FIRST(&dev->si_children)); dev->si_drv1 = 0; dev->si_drv2 = 0; dev->si_devsw = 0; bzero(&dev->__si_u, sizeof(dev->__si_u)); dev->si_flags &= ~SI_NAMED; dev->si_flags &= ~SI_ALIAS; freedev(dev); } const char * devtoname(dev_t dev) { char *p; int mynor; if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') { p = dev->si_name; if (devsw(dev)) sprintf(p, "#%s/", devsw(dev)->d_name); else sprintf(p, "#%d/", major(dev)); p += strlen(p); mynor = minor(dev); if (mynor < 0 || mynor > 255) sprintf(p, "%#x", (u_int)mynor); else sprintf(p, "%d", mynor); } return (dev->si_name); } int dev_stdclone(char *name, char **namep, const char *stem, int *unit) { int u, i; i = strlen(stem); if (bcmp(stem, name, i) != 0) return (0); if (!isdigit(name[i])) return (0); u = 0; if (name[i] == '0' && isdigit(name[i+1])) return (0); while (isdigit(name[i])) { u *= 10; u += name[i++] - '0'; } *unit = u; if (namep) *namep = &name[i]; if (name[i]) return (2); return (1); } /* * Helper sysctl for devname(3). We're given a {u}dev_t and return * the name, if any, registered by the device driver. */ static int sysctl_devname(SYSCTL_HANDLER_ARGS) { int error; udev_t ud; dev_t dev; error = SYSCTL_IN(req, &ud, sizeof (ud)); if (error) return (error); if (ud == NOUDEV) return(EINVAL); dev = makedev(umajor(ud), uminor(ud)); if (dev->si_name[0] == '\0') error = ENOENT; else error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1); freedev(dev); return (error); } SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY, NULL, 0, sysctl_devname, "", "devname(3) handler"); /* * Set ready_for_devs; prior to this point, device creation is not allowed. */ static void dev_set_ready(void *junk) { ready_for_devs = 1; } SYSINIT(dev_ready, SI_SUB_DEVFS, SI_ORDER_FIRST, dev_set_ready, NULL); diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index ebcba9463ec2..b739a17ddd99 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -1,336 +1,336 @@ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Mike Karels at Berkeley Software Design, Inc. * * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD * project, to make these variables more userfriendly. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 * $FreeBSD$ */ #include "opt_posix.h" #include #include #include #include #include #include #include #include #include SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, "Sysctl internal magic"); SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, "High kernel, proc, limits &c"); SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, "Virtual memory"); SYSCTL_NODE(, CTL_VFS, vfs, CTLFLAG_RW, 0, "File system"); SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0, "Network, (see socket.h)"); SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0, "Debugging"); SYSCTL_NODE(_debug, OID_AUTO, sizeof, CTLFLAG_RW, 0, "Sizeof various things"); SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0, "hardware"); SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0, "machine dependent"); SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, "user-level"); SYSCTL_NODE(, CTL_P1003_1B, p1003_1b, CTLFLAG_RW, 0, "p1003_1b, (see p1003_1b.h)"); SYSCTL_NODE(, OID_AUTO, compat, CTLFLAG_RW, 0, "Compatibility code"); SYSCTL_NODE(, OID_AUTO, security, CTLFLAG_RW, 0, "Security"); #ifdef REGRESSION SYSCTL_NODE(, OID_AUTO, regression, CTLFLAG_RW, 0, "Regression test MIB"); #endif SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, "Operating system release"); SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, "Operating system revision"); SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD, version, 0, "Kernel version"); SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD, ostype, 0, "Operating system type"); extern int osreldate; SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, &osreldate, 0, "Operating system release date"); SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD, &maxproc, 0, "Maximum number of processes"); SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, CTLFLAG_RW, &maxprocperuid, 0, "Maximum processes allowed per userid"); SYSCTL_INT(_kern, OID_AUTO, maxusers, CTLFLAG_RD, &maxusers, 0, "Hint for kernel tuning"); SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, 0, ARG_MAX, "Maximum bytes of argument to execve(2)"); SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, 0, _KPOSIX_VERSION, "Version of POSIX attempting to comply to"); SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD, 0, NGROUPS_MAX, "Maximum number of groups a user can belong to"); SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, 0, 1, "Whether job control is available"); #ifdef _POSIX_SAVED_IDS SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 1, "Whether saved set-group/user ID is available"); #else SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, 0, 0, "Whether saved set-group/user ID is available"); #endif char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW, kernelname, sizeof kernelname, "Name of kernel file booted"); #ifdef SMP SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, &mp_ncpus, 0, "Number of active CPUs"); #else SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, 0, 1, "Number of active CPUs"); #endif SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, 0, BYTE_ORDER, "System byte order"); SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, 0, PAGE_SIZE, "System memory page size"); static char machine_arch[] = MACHINE_ARCH; SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD, machine_arch, 0, "System architecture"); char hostname[MAXHOSTNAMELEN]; static int sysctl_hostname(SYSCTL_HANDLER_ARGS) { struct prison *pr; char tmphostname[MAXHOSTNAMELEN]; int error; pr = req->td->td_ucred->cr_prison; if (pr != NULL) { if (!jail_set_hostname_allowed && req->newptr) return (EPERM); /* * Process is in jail, so make a local copy of jail * hostname to get/set so we don't have to hold the jail * mutex during the sysctl copyin/copyout activities. */ mtx_lock(&pr->pr_mtx); bcopy(pr->pr_host, tmphostname, MAXHOSTNAMELEN); mtx_unlock(&pr->pr_mtx); error = sysctl_handle_string(oidp, tmphostname, sizeof pr->pr_host, req); if (req->newptr != NULL && error == 0) { /* * Copy the locally set hostname to the jail, if * appropriate. */ mtx_lock(&pr->pr_mtx); bcopy(tmphostname, pr->pr_host, MAXHOSTNAMELEN); mtx_unlock(&pr->pr_mtx); } } else error = sysctl_handle_string(oidp, hostname, sizeof hostname, req); return (error); } SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_hostname, "A", "Hostname"); static int regression_securelevel_nonmonotonic = 0; #ifdef REGRESSION SYSCTL_INT(_regression, OID_AUTO, securelevel_nonmonotonic, CTLFLAG_RW, ®ression_securelevel_nonmonotonic, 0, "securelevel may be lowered"); #endif int securelevel = -1; struct mtx securelevel_mtx; MTX_SYSINIT(securelevel_lock, &securelevel_mtx, "securelevel mutex lock", MTX_DEF); static int sysctl_kern_securelvl(SYSCTL_HANDLER_ARGS) { struct prison *pr; int error, level; pr = req->td->td_ucred->cr_prison; /* * If the process is in jail, return the maximum of the global and * local levels; otherwise, return the global level. */ if (pr != NULL) { mtx_lock(&pr->pr_mtx); level = imax(securelevel, pr->pr_securelevel); mtx_unlock(&pr->pr_mtx); } else level = securelevel; error = sysctl_handle_int(oidp, &level, 0, req); if (error || !req->newptr) return (error); /* * Permit update only if the new securelevel exceeds the * global level, and local level if any. */ if (pr != NULL) { mtx_lock(&pr->pr_mtx); if (!regression_securelevel_nonmonotonic && (level < imax(securelevel, pr->pr_securelevel))) { mtx_unlock(&pr->pr_mtx); return (EPERM); } pr->pr_securelevel = level; mtx_unlock(&pr->pr_mtx); } else { mtx_lock(&securelevel_mtx); if (!regression_securelevel_nonmonotonic && (level < securelevel)) { mtx_unlock(&securelevel_mtx); return (EPERM); } securelevel = level; mtx_unlock(&securelevel_mtx); } return (error); } SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_kern_securelvl, "I", "Current secure level"); char domainname[MAXHOSTNAMELEN]; SYSCTL_STRING(_kern, KERN_NISDOMAINNAME, domainname, CTLFLAG_RW, &domainname, sizeof(domainname), "Name of the current YP/NIS domain"); u_long hostid; SYSCTL_ULONG(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, "Host ID"); /* * This is really cheating. These actually live in the libc, something * which I'm not quite sure is a good idea anyway, but in order for * getnext and friends to actually work, we define dummies here. */ SYSCTL_STRING(_user, USER_CS_PATH, cs_path, CTLFLAG_RD, "", 0, "PATH that finds all the standard utilities"); SYSCTL_INT(_user, USER_BC_BASE_MAX, bc_base_max, CTLFLAG_RD, 0, 0, "Max ibase/obase values in bc(1)"); SYSCTL_INT(_user, USER_BC_DIM_MAX, bc_dim_max, CTLFLAG_RD, 0, 0, "Max array size in bc(1)"); SYSCTL_INT(_user, USER_BC_SCALE_MAX, bc_scale_max, CTLFLAG_RD, 0, 0, "Max scale value in bc(1)"); SYSCTL_INT(_user, USER_BC_STRING_MAX, bc_string_max, CTLFLAG_RD, 0, 0, "Max string length in bc(1)"); SYSCTL_INT(_user, USER_COLL_WEIGHTS_MAX, coll_weights_max, CTLFLAG_RD, 0, 0, "Maximum number of weights assigned to an LC_COLLATE locale entry"); SYSCTL_INT(_user, USER_EXPR_NEST_MAX, expr_nest_max, CTLFLAG_RD, 0, 0, ""); SYSCTL_INT(_user, USER_LINE_MAX, line_max, CTLFLAG_RD, 0, 0, "Max length (bytes) of a text-processing utility's input line"); SYSCTL_INT(_user, USER_RE_DUP_MAX, re_dup_max, CTLFLAG_RD, 0, 0, "Maximum number of repeats of a regexp permitted"); SYSCTL_INT(_user, USER_POSIX2_VERSION, posix2_version, CTLFLAG_RD, 0, 0, "The version of POSIX 1003.2 with which the system attempts to comply"); SYSCTL_INT(_user, USER_POSIX2_C_BIND, posix2_c_bind, CTLFLAG_RD, 0, 0, "Whether C development supports the C bindings option"); SYSCTL_INT(_user, USER_POSIX2_C_DEV, posix2_c_dev, CTLFLAG_RD, 0, 0, "Whether system supports the C development utilities option"); SYSCTL_INT(_user, USER_POSIX2_CHAR_TERM, posix2_char_term, CTLFLAG_RD, 0, 0, ""); SYSCTL_INT(_user, USER_POSIX2_FORT_DEV, posix2_fort_dev, CTLFLAG_RD, 0, 0, "Whether system supports FORTRAN development utilities"); SYSCTL_INT(_user, USER_POSIX2_FORT_RUN, posix2_fort_run, CTLFLAG_RD, 0, 0, "Whether system supports FORTRAN runtime utilities"); SYSCTL_INT(_user, USER_POSIX2_LOCALEDEF, posix2_localedef, CTLFLAG_RD, 0, 0, "Whether system supports creation of locales"); SYSCTL_INT(_user, USER_POSIX2_SW_DEV, posix2_sw_dev, CTLFLAG_RD, 0, 0, "Whether system supports software development utilities"); SYSCTL_INT(_user, USER_POSIX2_UPE, posix2_upe, CTLFLAG_RD, 0, 0, "Whether system supports the user portability utilities"); SYSCTL_INT(_user, USER_STREAM_MAX, stream_max, CTLFLAG_RD, 0, 0, "Min Maximum number of streams a process may have open at one time"); SYSCTL_INT(_user, USER_TZNAME_MAX, tzname_max, CTLFLAG_RD, 0, 0, "Min Maximum number of types supported for timezone names"); #include SYSCTL_INT(_debug_sizeof, OID_AUTO, vnode, CTLFLAG_RD, 0, sizeof(struct vnode), "sizeof(struct vnode)"); SYSCTL_INT(_debug_sizeof, OID_AUTO, proc, CTLFLAG_RD, 0, sizeof(struct proc), "sizeof(struct proc)"); #include -SYSCTL_INT(_debug_sizeof, OID_AUTO, specinfo, CTLFLAG_RD, - 0, sizeof(struct specinfo), "sizeof(struct specinfo)"); +SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev, CTLFLAG_RD, + 0, sizeof(struct cdev), "sizeof(struct cdev)"); #include #include SYSCTL_INT(_debug_sizeof, OID_AUTO, bio, CTLFLAG_RD, 0, sizeof(struct bio), "sizeof(struct bio)"); SYSCTL_INT(_debug_sizeof, OID_AUTO, buf, CTLFLAG_RD, 0, sizeof(struct buf), "sizeof(struct buf)"); #include SYSCTL_INT(_debug_sizeof, OID_AUTO, kinfo_proc, CTLFLAG_RD, 0, sizeof(struct kinfo_proc), "sizeof(struct kinfo_proc)"); diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 97fa2729fec8..35ac4c2afdba 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -1,382 +1,382 @@ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 2000 * Poul-Henning Kamp. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)conf.h 8.5 (Berkeley) 1/9/95 * $FreeBSD$ */ #ifndef _SYS_CONF_H_ #define _SYS_CONF_H_ #ifdef _KERNEL #include struct tty; struct disk; struct vnode; struct buf; TAILQ_HEAD(snaphead, inode); -struct specinfo { +struct cdev { u_int si_flags; #define SI_STASHED 0x0001 /* created in stashed storage */ #define SI_ALIAS 0x0002 /* carrier of alias name */ #define SI_NAMED 0x0004 /* make_dev{_alias} has been called */ #define SI_CHEAPCLONE 0x0008 /* can be removed_dev'ed when vnode reclaims */ #define SI_CHILD 0x0010 /* child of another dev_t */ #define SI_DEVOPEN 0x0020 /* opened by device */ #define SI_CONSOPEN 0x0040 /* opened by console */ #define SI_DUMPDEV 0x0080 /* is kernel dumpdev */ struct timespec si_atime; struct timespec si_ctime; struct timespec si_mtime; udev_t si_udev; - LIST_ENTRY(specinfo) si_hash; + LIST_ENTRY(cdev) si_hash; SLIST_HEAD(, vnode) si_hlist; - LIST_HEAD(, specinfo) si_children; - LIST_ENTRY(specinfo) si_siblings; + LIST_HEAD(, cdev) si_children; + LIST_ENTRY(cdev) si_siblings; dev_t si_parent; struct snaphead si_snapshots; int (*si_copyonwrite)(struct vnode *, struct buf *); u_int si_inode; char si_name[SPECNAMELEN + 1]; void *si_drv1, *si_drv2; struct cdevsw *si_devsw; int si_iosize_max; /* maximum I/O size (for physio &al) */ uid_t si_uid; gid_t si_gid; mode_t si_mode; union { struct { struct tty *__sit_tty; } __si_tty; struct { struct disk *__sid_disk; struct mount *__sid_mountpoint; int __sid_bsize_phys; /* min physical block size */ int __sid_bsize_best; /* optimal block size */ } __si_disk; } __si_u; }; #define si_tty __si_u.__si_tty.__sit_tty #define si_disk __si_u.__si_disk.__sid_disk #define si_mountpoint __si_u.__si_disk.__sid_mountpoint #define si_bsize_phys __si_u.__si_disk.__sid_bsize_phys #define si_bsize_best __si_u.__si_disk.__sid_bsize_best /* * Special device management */ #define SPECHSZ 64 #define SPECHASH(rdev) (((unsigned)(minor(rdev)))%SPECHSZ) /* * Definitions of device driver entry switches */ struct bio; struct buf; struct thread; struct uio; struct knote; /* * Note: d_thread_t is provided as a transition aid for those drivers * that treat struct proc/struct thread as an opaque data type and * exist in substantially the same form in both 4.x and 5.x. Writers * of drivers that dips into the d_thread_t structure should use * struct thread or struct proc as appropriate for the version of the * OS they are using. It is provided in lieu of each device driver * inventing its own way of doing this. While it does violate style(9) * in a number of ways, this violation is deemed to be less * important than the benefits that a uniform API between releases * gives. * * Users of struct thread/struct proc that aren't device drivers should * not use d_thread_t. */ typedef struct thread d_thread_t; typedef int d_open_t(dev_t dev, int oflags, int devtype, struct thread *td); typedef int d_close_t(dev_t dev, int fflag, int devtype, struct thread *td); typedef void d_strategy_t(struct bio *bp); typedef int d_ioctl_t(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td); typedef int d_dump_t(dev_t dev,void *virtual, vm_offset_t physical, off_t offset, size_t length); typedef int d_psize_t(dev_t dev); typedef int d_read_t(dev_t dev, struct uio *uio, int ioflag); typedef int d_write_t(dev_t dev, struct uio *uio, int ioflag); typedef int d_poll_t(dev_t dev, int events, struct thread *td); typedef int d_kqfilter_t(dev_t dev, struct knote *kn); typedef int d_mmap_t(dev_t dev, vm_offset_t offset, int nprot); typedef int l_open_t(dev_t dev, struct tty *tp); typedef int l_close_t(struct tty *tp, int flag); typedef int l_read_t(struct tty *tp, struct uio *uio, int flag); typedef int l_write_t(struct tty *tp, struct uio *uio, int flag); typedef int l_ioctl_t(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td); typedef int l_rint_t(int c, struct tty *tp); typedef int l_start_t(struct tty *tp); typedef int l_modem_t(struct tty *tp, int flag); /* * XXX: The dummy argument can be used to do what strategy1() never * did anywhere: Create a per device flag to lock the device during * label/slice surgery, all calls with a dummy == 0 gets stalled on * a queue somewhere, whereas dummy == 1 are let through. Once out * of surgery, reset the flag and restart all the stuff on the stall * queue. */ #define BIO_STRATEGY(bp, dummy) \ do { \ if ((!(bp)->bio_cmd) || ((bp)->bio_cmd & ((bp)->bio_cmd - 1))) \ Debugger("bio_cmd botch"); \ (*devsw((bp)->bio_dev)->d_strategy)(bp); \ } while (0) #define DEV_STRATEGY(bp, dummy) \ do { \ if ((bp)->b_flags & B_PHYS) \ (bp)->b_io.bio_offset = (bp)->b_offset; \ else \ (bp)->b_io.bio_offset = dbtob((bp)->b_blkno); \ (bp)->b_io.bio_done = bufdonebio; \ (bp)->b_io.bio_caller2 = (bp); \ BIO_STRATEGY(&(bp)->b_io, dummy); \ } while (0) #endif /* _KERNEL */ /* * Types for d_flags. */ #define D_TAPE 0x0001 #define D_DISK 0x0002 #define D_TTY 0x0004 #define D_MEM 0x0008 #ifdef _KERNEL #define D_TYPEMASK 0xffff /* * Flags for d_flags. */ #define D_MEMDISK 0x00010000 /* memory type disk */ #define D_NAGGED 0x00020000 /* nagged about missing make_dev() */ #define D_CANFREE 0x00040000 /* can free blocks */ #define D_TRACKCLOSE 0x00080000 /* track all closes */ #define D_MMAP_ANON 0x00100000 /* special treatment in vm_mmap.c */ #define D_KQFILTER 0x00200000 /* has kqfilter entry */ /* * Character device switch table */ struct cdevsw { d_open_t *d_open; d_close_t *d_close; d_read_t *d_read; d_write_t *d_write; d_ioctl_t *d_ioctl; d_poll_t *d_poll; d_mmap_t *d_mmap; d_strategy_t *d_strategy; const char *d_name; /* base device name, e.g. 'vn' */ int d_maj; d_dump_t *d_dump; d_psize_t *d_psize; u_int d_flags; /* additions below are not binary compatible with 4.2 and below */ d_kqfilter_t *d_kqfilter; }; /* * Line discipline switch table */ struct linesw { l_open_t *l_open; l_close_t *l_close; l_read_t *l_read; l_write_t *l_write; l_ioctl_t *l_ioctl; l_rint_t *l_rint; l_start_t *l_start; l_modem_t *l_modem; u_char l_hotchar; }; extern struct linesw linesw[]; extern int nlinesw; int ldisc_register(int , struct linesw *); void ldisc_deregister(int); #define LDISC_LOAD -1 /* Loadable line discipline */ #endif /* _KERNEL */ /* * Swap device table */ struct swdevt { udev_t sw_dev; /* For quasibogus swapdev reporting */ int sw_flags; int sw_nblks; int sw_used; struct vnode *sw_vp; dev_t sw_device; }; #define SW_FREED 0x01 #define SW_SEQUENTIAL 0x02 #define sw_freed sw_flags /* XXX compat */ #ifdef _KERNEL d_open_t noopen; d_close_t noclose; d_read_t noread; d_write_t nowrite; d_ioctl_t noioctl; d_mmap_t nommap; d_kqfilter_t nokqfilter; #define nostrategy ((d_strategy_t *)NULL) #define nopoll seltrue d_dump_t nodump; #define NUMCDEVSW 256 /* * nopsize is little used, so not worth having dummy functions for. */ #define nopsize ((d_psize_t *)NULL) d_open_t nullopen; d_close_t nullclose; l_ioctl_t l_nullioctl; l_read_t l_noread; l_write_t l_nowrite; struct module; struct devsw_module_data { int (*chainevh)(struct module *, int, void *); /* next handler */ void *chainarg; /* arg for next event handler */ /* Do not initialize fields hereafter */ }; #define DEV_MODULE(name, evh, arg) \ static moduledata_t name##_mod = { \ #name, \ evh, \ arg \ }; \ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE) int cdevsw_add(struct cdevsw *_new); int cdevsw_remove(struct cdevsw *_old); int count_dev(dev_t _dev); void destroy_dev(dev_t _dev); void revoke_and_destroy_dev(dev_t _dev); struct cdevsw *devsw(dev_t _dev); const char *devtoname(dev_t _dev); int dev_named(dev_t _pdev, const char *_name); void dev_depends(dev_t _pdev, dev_t _cdev); void freedev(dev_t _dev); int iszerodev(dev_t _dev); dev_t makebdev(int _maj, int _min); dev_t make_dev(struct cdevsw *_devsw, int _minor, uid_t _uid, gid_t _gid, int _perms, const char *_fmt, ...) __printflike(6, 7); dev_t make_dev_alias(dev_t _pdev, const char *_fmt, ...) __printflike(2, 3); int dev2unit(dev_t _dev); int unit2minor(int _unit); void setconf(void); dev_t getdiskbyname(char *_name); /* This is type of the function DEVFS uses to hook into the kernel with */ typedef void devfs_create_t(dev_t dev); typedef void devfs_destroy_t(dev_t dev); extern devfs_create_t *devfs_create_hook; extern devfs_destroy_t *devfs_destroy_hook; extern int devfs_present; #define UID_ROOT 0 #define UID_BIN 3 #define UID_UUCP 66 #define GID_WHEEL 0 #define GID_KMEM 2 #define GID_OPERATOR 5 #define GID_BIN 7 #define GID_GAMES 13 #define GID_DIALER 68 typedef void (*dev_clone_fn)(void *arg, char *name, int namelen, dev_t *result); int dev_stdclone(char *_name, char **_namep, const char *_stem, int *_unit); EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn); /* Stuff relating to kernel-dump */ typedef int dumper_t( void *priv, /* Private to the driver. */ void *virtual, /* Virtual (mapped) address. */ vm_offset_t physical, /* Physical address of virtual. */ off_t offset, /* Byte-offset to write at. */ size_t length); /* Number of bytes to dump. */ struct dumperinfo { dumper_t *dumper; /* Dumping function. */ void *priv; /* Private parts. */ u_int blocksize; /* Size of block in bytes. */ off_t mediaoffset; /* Initial offset in bytes. */ off_t mediasize; /* Space available in bytes. */ }; int set_dumper(struct dumperinfo *); void dumpsys(struct dumperinfo *); extern int dumping; /* system is dumping */ #endif /* _KERNEL */ #endif /* !_SYS_CONF_H_ */ diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h index 97fa2729fec8..35ac4c2afdba 100644 --- a/sys/sys/linedisc.h +++ b/sys/sys/linedisc.h @@ -1,382 +1,382 @@ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 2000 * Poul-Henning Kamp. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)conf.h 8.5 (Berkeley) 1/9/95 * $FreeBSD$ */ #ifndef _SYS_CONF_H_ #define _SYS_CONF_H_ #ifdef _KERNEL #include struct tty; struct disk; struct vnode; struct buf; TAILQ_HEAD(snaphead, inode); -struct specinfo { +struct cdev { u_int si_flags; #define SI_STASHED 0x0001 /* created in stashed storage */ #define SI_ALIAS 0x0002 /* carrier of alias name */ #define SI_NAMED 0x0004 /* make_dev{_alias} has been called */ #define SI_CHEAPCLONE 0x0008 /* can be removed_dev'ed when vnode reclaims */ #define SI_CHILD 0x0010 /* child of another dev_t */ #define SI_DEVOPEN 0x0020 /* opened by device */ #define SI_CONSOPEN 0x0040 /* opened by console */ #define SI_DUMPDEV 0x0080 /* is kernel dumpdev */ struct timespec si_atime; struct timespec si_ctime; struct timespec si_mtime; udev_t si_udev; - LIST_ENTRY(specinfo) si_hash; + LIST_ENTRY(cdev) si_hash; SLIST_HEAD(, vnode) si_hlist; - LIST_HEAD(, specinfo) si_children; - LIST_ENTRY(specinfo) si_siblings; + LIST_HEAD(, cdev) si_children; + LIST_ENTRY(cdev) si_siblings; dev_t si_parent; struct snaphead si_snapshots; int (*si_copyonwrite)(struct vnode *, struct buf *); u_int si_inode; char si_name[SPECNAMELEN + 1]; void *si_drv1, *si_drv2; struct cdevsw *si_devsw; int si_iosize_max; /* maximum I/O size (for physio &al) */ uid_t si_uid; gid_t si_gid; mode_t si_mode; union { struct { struct tty *__sit_tty; } __si_tty; struct { struct disk *__sid_disk; struct mount *__sid_mountpoint; int __sid_bsize_phys; /* min physical block size */ int __sid_bsize_best; /* optimal block size */ } __si_disk; } __si_u; }; #define si_tty __si_u.__si_tty.__sit_tty #define si_disk __si_u.__si_disk.__sid_disk #define si_mountpoint __si_u.__si_disk.__sid_mountpoint #define si_bsize_phys __si_u.__si_disk.__sid_bsize_phys #define si_bsize_best __si_u.__si_disk.__sid_bsize_best /* * Special device management */ #define SPECHSZ 64 #define SPECHASH(rdev) (((unsigned)(minor(rdev)))%SPECHSZ) /* * Definitions of device driver entry switches */ struct bio; struct buf; struct thread; struct uio; struct knote; /* * Note: d_thread_t is provided as a transition aid for those drivers * that treat struct proc/struct thread as an opaque data type and * exist in substantially the same form in both 4.x and 5.x. Writers * of drivers that dips into the d_thread_t structure should use * struct thread or struct proc as appropriate for the version of the * OS they are using. It is provided in lieu of each device driver * inventing its own way of doing this. While it does violate style(9) * in a number of ways, this violation is deemed to be less * important than the benefits that a uniform API between releases * gives. * * Users of struct thread/struct proc that aren't device drivers should * not use d_thread_t. */ typedef struct thread d_thread_t; typedef int d_open_t(dev_t dev, int oflags, int devtype, struct thread *td); typedef int d_close_t(dev_t dev, int fflag, int devtype, struct thread *td); typedef void d_strategy_t(struct bio *bp); typedef int d_ioctl_t(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td); typedef int d_dump_t(dev_t dev,void *virtual, vm_offset_t physical, off_t offset, size_t length); typedef int d_psize_t(dev_t dev); typedef int d_read_t(dev_t dev, struct uio *uio, int ioflag); typedef int d_write_t(dev_t dev, struct uio *uio, int ioflag); typedef int d_poll_t(dev_t dev, int events, struct thread *td); typedef int d_kqfilter_t(dev_t dev, struct knote *kn); typedef int d_mmap_t(dev_t dev, vm_offset_t offset, int nprot); typedef int l_open_t(dev_t dev, struct tty *tp); typedef int l_close_t(struct tty *tp, int flag); typedef int l_read_t(struct tty *tp, struct uio *uio, int flag); typedef int l_write_t(struct tty *tp, struct uio *uio, int flag); typedef int l_ioctl_t(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td); typedef int l_rint_t(int c, struct tty *tp); typedef int l_start_t(struct tty *tp); typedef int l_modem_t(struct tty *tp, int flag); /* * XXX: The dummy argument can be used to do what strategy1() never * did anywhere: Create a per device flag to lock the device during * label/slice surgery, all calls with a dummy == 0 gets stalled on * a queue somewhere, whereas dummy == 1 are let through. Once out * of surgery, reset the flag and restart all the stuff on the stall * queue. */ #define BIO_STRATEGY(bp, dummy) \ do { \ if ((!(bp)->bio_cmd) || ((bp)->bio_cmd & ((bp)->bio_cmd - 1))) \ Debugger("bio_cmd botch"); \ (*devsw((bp)->bio_dev)->d_strategy)(bp); \ } while (0) #define DEV_STRATEGY(bp, dummy) \ do { \ if ((bp)->b_flags & B_PHYS) \ (bp)->b_io.bio_offset = (bp)->b_offset; \ else \ (bp)->b_io.bio_offset = dbtob((bp)->b_blkno); \ (bp)->b_io.bio_done = bufdonebio; \ (bp)->b_io.bio_caller2 = (bp); \ BIO_STRATEGY(&(bp)->b_io, dummy); \ } while (0) #endif /* _KERNEL */ /* * Types for d_flags. */ #define D_TAPE 0x0001 #define D_DISK 0x0002 #define D_TTY 0x0004 #define D_MEM 0x0008 #ifdef _KERNEL #define D_TYPEMASK 0xffff /* * Flags for d_flags. */ #define D_MEMDISK 0x00010000 /* memory type disk */ #define D_NAGGED 0x00020000 /* nagged about missing make_dev() */ #define D_CANFREE 0x00040000 /* can free blocks */ #define D_TRACKCLOSE 0x00080000 /* track all closes */ #define D_MMAP_ANON 0x00100000 /* special treatment in vm_mmap.c */ #define D_KQFILTER 0x00200000 /* has kqfilter entry */ /* * Character device switch table */ struct cdevsw { d_open_t *d_open; d_close_t *d_close; d_read_t *d_read; d_write_t *d_write; d_ioctl_t *d_ioctl; d_poll_t *d_poll; d_mmap_t *d_mmap; d_strategy_t *d_strategy; const char *d_name; /* base device name, e.g. 'vn' */ int d_maj; d_dump_t *d_dump; d_psize_t *d_psize; u_int d_flags; /* additions below are not binary compatible with 4.2 and below */ d_kqfilter_t *d_kqfilter; }; /* * Line discipline switch table */ struct linesw { l_open_t *l_open; l_close_t *l_close; l_read_t *l_read; l_write_t *l_write; l_ioctl_t *l_ioctl; l_rint_t *l_rint; l_start_t *l_start; l_modem_t *l_modem; u_char l_hotchar; }; extern struct linesw linesw[]; extern int nlinesw; int ldisc_register(int , struct linesw *); void ldisc_deregister(int); #define LDISC_LOAD -1 /* Loadable line discipline */ #endif /* _KERNEL */ /* * Swap device table */ struct swdevt { udev_t sw_dev; /* For quasibogus swapdev reporting */ int sw_flags; int sw_nblks; int sw_used; struct vnode *sw_vp; dev_t sw_device; }; #define SW_FREED 0x01 #define SW_SEQUENTIAL 0x02 #define sw_freed sw_flags /* XXX compat */ #ifdef _KERNEL d_open_t noopen; d_close_t noclose; d_read_t noread; d_write_t nowrite; d_ioctl_t noioctl; d_mmap_t nommap; d_kqfilter_t nokqfilter; #define nostrategy ((d_strategy_t *)NULL) #define nopoll seltrue d_dump_t nodump; #define NUMCDEVSW 256 /* * nopsize is little used, so not worth having dummy functions for. */ #define nopsize ((d_psize_t *)NULL) d_open_t nullopen; d_close_t nullclose; l_ioctl_t l_nullioctl; l_read_t l_noread; l_write_t l_nowrite; struct module; struct devsw_module_data { int (*chainevh)(struct module *, int, void *); /* next handler */ void *chainarg; /* arg for next event handler */ /* Do not initialize fields hereafter */ }; #define DEV_MODULE(name, evh, arg) \ static moduledata_t name##_mod = { \ #name, \ evh, \ arg \ }; \ DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE) int cdevsw_add(struct cdevsw *_new); int cdevsw_remove(struct cdevsw *_old); int count_dev(dev_t _dev); void destroy_dev(dev_t _dev); void revoke_and_destroy_dev(dev_t _dev); struct cdevsw *devsw(dev_t _dev); const char *devtoname(dev_t _dev); int dev_named(dev_t _pdev, const char *_name); void dev_depends(dev_t _pdev, dev_t _cdev); void freedev(dev_t _dev); int iszerodev(dev_t _dev); dev_t makebdev(int _maj, int _min); dev_t make_dev(struct cdevsw *_devsw, int _minor, uid_t _uid, gid_t _gid, int _perms, const char *_fmt, ...) __printflike(6, 7); dev_t make_dev_alias(dev_t _pdev, const char *_fmt, ...) __printflike(2, 3); int dev2unit(dev_t _dev); int unit2minor(int _unit); void setconf(void); dev_t getdiskbyname(char *_name); /* This is type of the function DEVFS uses to hook into the kernel with */ typedef void devfs_create_t(dev_t dev); typedef void devfs_destroy_t(dev_t dev); extern devfs_create_t *devfs_create_hook; extern devfs_destroy_t *devfs_destroy_hook; extern int devfs_present; #define UID_ROOT 0 #define UID_BIN 3 #define UID_UUCP 66 #define GID_WHEEL 0 #define GID_KMEM 2 #define GID_OPERATOR 5 #define GID_BIN 7 #define GID_GAMES 13 #define GID_DIALER 68 typedef void (*dev_clone_fn)(void *arg, char *name, int namelen, dev_t *result); int dev_stdclone(char *_name, char **_namep, const char *_stem, int *_unit); EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn); /* Stuff relating to kernel-dump */ typedef int dumper_t( void *priv, /* Private to the driver. */ void *virtual, /* Virtual (mapped) address. */ vm_offset_t physical, /* Physical address of virtual. */ off_t offset, /* Byte-offset to write at. */ size_t length); /* Number of bytes to dump. */ struct dumperinfo { dumper_t *dumper; /* Dumping function. */ void *priv; /* Private parts. */ u_int blocksize; /* Size of block in bytes. */ off_t mediaoffset; /* Initial offset in bytes. */ off_t mediasize; /* Space available in bytes. */ }; int set_dumper(struct dumperinfo *); void dumpsys(struct dumperinfo *); extern int dumping; /* system is dumping */ #endif /* _KERNEL */ #endif /* !_SYS_CONF_H_ */ diff --git a/sys/sys/types.h b/sys/sys/types.h index a669c1338cf3..ad891b0cc4d4 100644 --- a/sys/sys/types.h +++ b/sys/sys/types.h @@ -1,294 +1,294 @@ /*- * Copyright (c) 1982, 1986, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)types.h 8.6 (Berkeley) 2/19/95 * $FreeBSD$ */ #ifndef _SYS_TYPES_H_ #define _SYS_TYPES_H_ #include /* Machine type dependent parameters. */ #include #include #ifndef _POSIX_SOURCE typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned short ushort; /* Sys V compatibility */ typedef unsigned int uint; /* Sys V compatibility */ #endif /* * XXX POSIX sized integrals that should appear only in . */ #ifndef _INT8_T_DECLARED typedef __int8_t int8_t; #define _INT8_T_DECLARED #endif #ifndef _INT16_T_DECLARED typedef __int16_t int16_t; #define _INT16_T_DECLARED #endif #ifndef _INT32_T_DECLARED typedef __int32_t int32_t; #define _INT32_T_DECLARED #endif #ifndef _INT64_T_DECLARED typedef __int64_t int64_t; #define _INT64_T_DECLARED #endif #ifndef _UINT8_T_DECLARED typedef __uint8_t uint8_t; #define _UINT8_T_DECLARED #endif #ifndef _UINT16_T_DECLARED typedef __uint16_t uint16_t; #define _UINT16_T_DECLARED #endif #ifndef _UINT32_T_DECLARED typedef __uint32_t uint32_t; #define _UINT32_T_DECLARED #endif #ifndef _UINT64_T_DECLARED typedef __uint64_t uint64_t; #define _UINT64_T_DECLARED #endif #ifndef _INTPTR_T_DECLARED typedef __intptr_t intptr_t; typedef __uintptr_t uintptr_t; #define _INTPTR_T_DECLARED #endif /* * Deprecated BSD unsigned integrals. */ typedef __uint8_t u_int8_t; typedef __uint16_t u_int16_t; typedef __uint32_t u_int32_t; typedef __uint64_t u_int64_t; /* * Deprecated BSD 64-bit integrals. */ typedef u_int64_t u_quad_t; /* quads */ typedef int64_t quad_t; typedef quad_t * qaddr_t; typedef char * caddr_t; /* core address */ typedef __const char * c_caddr_t; /* core address, pointer to const */ typedef __volatile char *v_caddr_t; /* core address, pointer to volatile */ typedef __critical_t critical_t; /* Critical section value */ typedef int64_t daddr_t; /* disk address */ typedef u_int32_t fixpt_t; /* fixed point number */ #ifndef _GID_T_DECLARED typedef __gid_t gid_t; /* group id */ #define _GID_T_DECLARED #endif typedef u_int32_t ino_t; /* inode number */ typedef long key_t; /* IPC key (for Sys V IPC) */ #ifndef _MODE_T_DECLARED typedef __mode_t mode_t; /* permissions */ #define _MODE_T_DECLARED #endif typedef u_int16_t nlink_t; /* link count */ #ifndef _OFF_T_DECLARED typedef __off_t off_t; /* file offset */ #define _OFF_T_DECLARED #endif #ifndef _PID_T_DECLARED typedef __pid_t pid_t; /* process id */ #define _PID_T_DECLARED #endif typedef __register_t register_t; typedef quad_t rlim_t; /* resource limit */ typedef __segsz_t segsz_t; /* segment size (in pages) */ typedef int32_t swblk_t; /* swap offset */ typedef __u_register_t u_register_t; #ifndef _UID_T_DECLARED typedef __uid_t uid_t; /* user id */ #define _UID_T_DECLARED #endif typedef __vm_offset_t vm_offset_t; typedef __vm_ooffset_t vm_ooffset_t; typedef __vm_pindex_t vm_pindex_t; typedef __vm_size_t vm_size_t; #ifdef _KERNEL typedef int boolean_t; typedef __intfptr_t intfptr_t; /*- * XXX this is fixed width for historical reasons. It should have had type * __int_fast32_t. Fixed-width types should not be used unless binary * compatibility is essential. Least-width types should be used even less * since they provide smaller benefits. * XXX should be MD. * XXX this is bogus in -current, but still used for spl*(). */ typedef __uint32_t intrmask_t; /* Interrupt mask (spl, xxx_imask...) */ typedef __uintfptr_t uintfptr_t; typedef u_int64_t uoff_t; typedef struct vm_page *vm_page_t; -struct specinfo; +struct cdev; typedef u_int32_t udev_t; /* device number */ -typedef struct specinfo *dev_t; +typedef struct cdev *dev_t; #define offsetof(type, field) __offsetof(type, field) #else /* !_KERNEL */ typedef u_int32_t dev_t; /* device number */ #define udev_t dev_t #if __BSD_VISIBLE /* * minor() gives a cookie instead of an index since we don't want to * change the meanings of bits 0-15 or waste time and space shifting * bits 16-31 for devices that don't use them. */ #define major(x) ((int)(((u_int)(x) >> 8)&0xff)) /* major number */ #define minor(x) ((int)((x)&0xffff00ff)) /* minor number */ #define makedev(x,y) ((dev_t)(((x) << 8) | (y))) /* create dev_t */ #endif /* __BSD_VISIBLE */ #endif /* !_KERNEL */ #ifndef _CLOCK_T_DECLARED typedef __clock_t clock_t; #define _CLOCK_T_DECLARED #endif #ifndef _CLOCKID_T_DECLARED typedef __clockid_t clockid_t; #define _CLOCKID_T_DECLARED #endif #ifndef _FFLAGS_T_DECLARED typedef __fflags_t fflags_t; /* file flags */ #define _FFLAGS_T_DECLARED #endif #ifndef _FSBLKCNT_T_DECLARED /* for statvfs() */ typedef __fsblkcnt_t fsblkcnt_t; typedef __fsfilcnt_t fsfilcnt_t; #define _FSBLKCNT_T_DECLARED #endif #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef _SSIZE_T_DECLARED typedef __ssize_t ssize_t; #define _SSIZE_T_DECLARED #endif #ifndef _TIME_T_DECLARED typedef __time_t time_t; #define _TIME_T_DECLARED #endif #ifndef _TIMER_T_DECLARED typedef __timer_t timer_t; #define _TIMER_T_DECLARED #endif /* * The following are all things that really shouldn't exist in this header, * since its purpose is to provide typedefs, not miscellaneous doodads. */ #if __BSD_VISIBLE #include /* * These declarations belong elsewhere, but are repeated here and in * to give broken programs a better chance of working with * 64-bit off_t's. */ #ifndef _KERNEL __BEGIN_DECLS #ifndef _FTRUNCATE_DECLARED #define _FTRUNCATE_DECLARED int ftruncate(int, off_t); #endif #ifndef _LSEEK_DECLARED #define _LSEEK_DECLARED off_t lseek(int, off_t, int); #endif #ifndef _MMAP_DECLARED #define _MMAP_DECLARED void * mmap(void *, size_t, int, int, int, off_t); #endif #ifndef _TRUNCATE_DECLARED #define _TRUNCATE_DECLARED int truncate(const char *, off_t); #endif __END_DECLS #endif /* !_KERNEL */ #endif /* __BSD_VISIBLE */ #endif /* !_SYS_TYPES_H_ */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 747c12cfa904..b6e8e843705e 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -1,726 +1,726 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)vnode.h 8.7 (Berkeley) 2/4/94 * $FreeBSD$ */ #ifndef _SYS_VNODE_H_ #define _SYS_VNODE_H_ /* * XXX - compatability until lockmgr() goes away or all the #includes are * updated. */ #include #include #include #include #include #include #include #include #include #include #include /* * The vnode is the focus of all file activity in UNIX. There is a * unique vnode allocated for each active file, each current directory, * each mounted-on file, text file, and the root. */ /* * Vnode types. VNON means no type. */ enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD }; /* * Each underlying filesystem allocates its own private area and hangs * it from v_data. If non-null, this area is freed in getnewvnode(). */ TAILQ_HEAD(buflists, buf); typedef int vop_t(void *); struct namecache; struct vpollinfo { struct mtx vpi_lock; /* lock to protect below */ struct selinfo vpi_selinfo; /* identity of poller(s) */ short vpi_events; /* what they are looking for */ short vpi_revents; /* what has happened */ }; /* * Reading or writing any of these items requires holding the appropriate lock. * * Lock reference: * c - namecache mutex * f - freelist mutex * i - interlock * m - mntvnodes mutex * p - pollinfo lock * s - spechash mutex * S - syncer mutex * u - Only a reference to the vnode is needed to read. * v - vnode lock * * XXX Not all fields are locked yet and some fields that are marked are not * locked consistently. This is a work in progress. */ struct vnode { struct mtx v_interlock; /* lock for "i" things */ u_long v_iflag; /* i vnode flags (see below) */ int v_usecount; /* i ref count of users */ long v_numoutput; /* i writes in progress */ struct thread *v_vxproc; /* i thread owning VXLOCK */ int v_holdcnt; /* i page & buffer references */ struct buflists v_cleanblkhd; /* i SORTED clean blocklist */ struct buf *v_cleanblkroot; /* i clean buf splay tree */ struct buflists v_dirtyblkhd; /* i SORTED dirty blocklist */ struct buf *v_dirtyblkroot; /* i dirty buf splay tree */ u_long v_vflag; /* v vnode flags */ int v_writecount; /* v ref count of writers */ struct vm_object *v_object; /* v Place to store VM object */ daddr_t v_lastw; /* v last write (write cluster) */ daddr_t v_cstart; /* v start block of cluster */ daddr_t v_lasta; /* v last allocation (cluster) */ int v_clen; /* v length of current cluster */ union { struct mount *vu_mountedhere;/* v ptr to mounted vfs (VDIR) */ struct socket *vu_socket; /* v unix ipc (VSOCK) */ struct { - struct specinfo *vu_specinfo; /* v device (VCHR, VBLK) */ + struct cdev *vu_cdev; /* v device (VCHR, VBLK) */ SLIST_ENTRY(vnode) vu_specnext; /* s device aliases */ } vu_spec; struct fifoinfo *vu_fifoinfo; /* v fifo (VFIFO) */ } v_un; TAILQ_ENTRY(vnode) v_freelist; /* f vnode freelist */ TAILQ_ENTRY(vnode) v_nmntvnodes; /* m vnodes for mount point */ LIST_ENTRY(vnode) v_synclist; /* S dirty vnode list */ enum vtype v_type; /* u vnode type */ const char *v_tag; /* u type of underlying data */ void *v_data; /* u private data for fs */ struct lock v_lock; /* u used if fs don't have one */ struct lock *v_vnlock; /* u pointer to vnode lock */ vop_t **v_op; /* u vnode operations vector */ struct mount *v_mount; /* u ptr to vfs we are in */ LIST_HEAD(, namecache) v_cache_src; /* c Cache entries from us */ TAILQ_HEAD(, namecache) v_cache_dst; /* c Cache entries to us */ u_long v_id; /* c capability identifier */ struct vnode *v_dd; /* c .. vnode */ u_long v_ddid; /* c .. capability identifier */ struct vpollinfo *v_pollinfo; /* p Poll events */ struct label v_label; /* MAC label for vnode */ #ifdef DEBUG_LOCKS const char *filename; /* Source file doing locking */ int line; /* Line number doing locking */ #endif udev_t v_cachedfs; /* cached fs id */ ino_t v_cachedid; /* cached file id */ }; #define v_mountedhere v_un.vu_mountedhere #define v_socket v_un.vu_socket -#define v_rdev v_un.vu_spec.vu_specinfo +#define v_rdev v_un.vu_spec.vu_cdev #define v_specnext v_un.vu_spec.vu_specnext #define v_fifoinfo v_un.vu_fifoinfo /* * Userland version of struct vnode, for sysctl. */ struct xvnode { size_t xv_size; /* sizeof(struct xvnode) */ void *xv_vnode; /* address of real vnode */ u_long xv_flag; /* vnode vflags */ int xv_usecount; /* reference count of users */ int xv_writecount; /* reference count of writers */ int xv_holdcnt; /* page & buffer references */ u_long xv_id; /* capability identifier */ void *xv_mount; /* address of parent mount */ long xv_numoutput; /* num of writes in progress */ enum vtype xv_type; /* vnode type */ union { void *xvu_socket; /* socket, if VSOCK */ void *xvu_fifo; /* fifo, if VFIFO */ udev_t xvu_rdev; /* maj/min, if VBLK/VCHR */ struct { udev_t xvu_dev; /* device, if VDIR/VREG/VLNK */ ino_t xvu_ino; /* id, if VDIR/VREG/VLNK */ }; } xv_un; }; #define xv_socket xv_un.xvu_socket #define xv_fifo xv_un.xvu_fifo #define xv_rdev xv_un.xvu_rdev #define xv_dev xv_un.xvu_dev #define xv_ino xv_un.xvu_ino #define VN_POLLEVENT(vp, events) \ do { \ if ((vp)->v_pollinfo != NULL && \ (vp)->v_pollinfo->vpi_events & (events)) \ vn_pollevent((vp), (events)); \ } while (0) #define VN_KNOTE(vp, b) \ do { \ if ((vp)->v_pollinfo != NULL) \ KNOTE(&vp->v_pollinfo->vpi_selinfo.si_note, (b)); \ } while (0) /* * Vnode flags. * VI flags are protected by interlock and live in v_iflag * VV flags are protected by the vnode lock and live in v_vflag */ #define VI_XLOCK 0x0001 /* vnode is locked to change vtype */ #define VI_XWANT 0x0002 /* thread is waiting for vnode */ #define VI_BWAIT 0x0004 /* waiting for output to complete */ #define VI_OLOCK 0x0008 /* vnode is locked waiting for an object */ #define VI_OWANT 0x0010 /* a thread is waiting for VOLOCK */ #define VI_MOUNT 0x0020 /* Mount in progress */ #define VI_AGE 0x0040 /* Insert vnode at head of free list */ #define VI_DOOMED 0x0080 /* This vnode is being recycled */ #define VI_FREE 0x0100 /* This vnode is on the freelist */ #define VI_OBJDIRTY 0x0400 /* object might be dirty */ /* * XXX VI_ONWORKLST could be replaced with a check for NULL list elements * in v_synclist. */ #define VI_ONWORKLST 0x0200 /* On syncer work-list */ #define VV_ROOT 0x0001 /* root of its filesystem */ #define VV_ISTTY 0x0002 /* vnode represents a tty */ #define VV_NOSYNC 0x0004 /* unlinked, stop syncing */ #define VV_OBJBUF 0x0008 /* Allocate buffers in VM object */ #define VV_CACHEDLABEL 0x0010 /* Vnode has valid cached MAC label */ #define VV_TEXT 0x0020 /* vnode is a pure text prototype */ #define VV_COPYONWRITE 0x0040 /* vnode is doing copy-on-write */ #define VV_SYSTEM 0x0080 /* vnode being used by kernel */ #define VV_PROCDEP 0x0100 /* vnode is process dependent */ /* * Vnode attributes. A field value of VNOVAL represents a field whose value * is unavailable (getattr) or which is not to be changed (setattr). */ struct vattr { enum vtype va_type; /* vnode type (for create) */ u_short va_mode; /* files access mode and type */ short va_nlink; /* number of references to file */ uid_t va_uid; /* owner user id */ gid_t va_gid; /* owner group id */ udev_t va_fsid; /* filesystem id */ long va_fileid; /* file id */ u_quad_t va_size; /* file size in bytes */ long va_blocksize; /* blocksize preferred for i/o */ struct timespec va_atime; /* time of last access */ struct timespec va_mtime; /* time of last modification */ struct timespec va_ctime; /* time file changed */ struct timespec va_birthtime; /* time file created */ u_long va_gen; /* generation number of file */ u_long va_flags; /* flags defined for file */ udev_t va_rdev; /* device the special file represents */ u_quad_t va_bytes; /* bytes of disk space held by file */ u_quad_t va_filerev; /* file modification number */ u_int va_vaflags; /* operations flags, see below */ long va_spare; /* remain quad aligned */ }; /* * Flags for va_vaflags. */ #define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */ #define VA_EXCLUSIVE 0x02 /* exclusive create request */ /* * Flags for ioflag. (high 16 bits used to ask for read-ahead and * help with write clustering) */ #define IO_UNIT 0x0001 /* do I/O as atomic unit */ #define IO_APPEND 0x0002 /* append write to end */ #define IO_SYNC 0x0004 /* do I/O synchronously */ #define IO_NODELOCKED 0x0008 /* underlying node already locked */ #define IO_NDELAY 0x0010 /* FNDELAY flag set in file table */ #define IO_VMIO 0x0020 /* data already in VMIO space */ #define IO_INVAL 0x0040 /* invalidate after I/O */ #define IO_ASYNC 0x0080 /* bawrite rather then bdwrite */ #define IO_DIRECT 0x0100 /* attempt to bypass buffer cache */ #define IO_NOWDRAIN 0x0200 /* do not block on wdrain */ #define IO_EXT 0x0400 /* operate on external attributes */ #define IO_NORMAL 0x0800 /* operate on regular data */ #define IO_NOMACCHECK 0x1000 /* MAC checks unnecessary */ /* * Modes. Some values same as Ixxx entries from inode.h for now. */ #define VEXEC 000100 /* execute/search permission */ #define VWRITE 000200 /* write permission */ #define VREAD 000400 /* read permission */ #define VSVTX 001000 /* save swapped text even after use */ #define VSGID 002000 /* set group id on execution */ #define VSUID 004000 /* set user id on execution */ #define VADMIN 010000 /* permission to administer */ #define VSTAT 020000 /* permission to retrieve attrs */ #define VAPPEND 040000 /* permission to write/append */ #define VALLPERM (VEXEC | VWRITE | VREAD | VADMIN | VSTAT | VAPPEND) /* * Token indicating no attribute value yet assigned. */ #define VNOVAL (-1) /* * LK_TIMELOCK timeout for vnode locks (used mainly by the pageout daemon) */ #define VLKTIMEOUT (hz / 20 + 1) #ifdef _KERNEL #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_VNODE); #endif /* * Convert between vnode types and inode formats (since POSIX.1 * defines mode word of stat structure in terms of inode formats). */ extern enum vtype iftovt_tab[]; extern int vttoif_tab[]; #define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12]) #define VTTOIF(indx) (vttoif_tab[(int)(indx)]) #define MAKEIMODE(indx, mode) (int)(VTTOIF(indx) | (mode)) /* * Flags to various vnode functions. */ #define SKIPSYSTEM 0x0001 /* vflush: skip vnodes marked VSYSTEM */ #define FORCECLOSE 0x0002 /* vflush: force file closure */ #define WRITECLOSE 0x0004 /* vflush: only close writable files */ #define DOCLOSE 0x0008 /* vclean: close active files */ #define V_SAVE 0x0001 /* vinvalbuf: sync file first */ #define V_ALT 0x0002 /* vinvalbuf: invalidate only alternate bufs */ #define V_NORMAL 0x0004 /* vinvalbuf: invalidate only regular bufs */ #define REVOKEALL 0x0001 /* vop_revoke: revoke all aliases */ #define V_WAIT 0x0001 /* vn_start_write: sleep for suspend */ #define V_NOWAIT 0x0002 /* vn_start_write: don't sleep for suspend */ #define V_XSLEEP 0x0004 /* vn_start_write: just return after sleep */ #define VREF(vp) vref(vp) #ifdef DIAGNOSTIC #define VATTR_NULL(vap) vattr_null(vap) #else #define VATTR_NULL(vap) (*(vap) = va_null) /* initialize a vattr */ #endif /* DIAGNOSTIC */ #define NULLVP ((struct vnode *)NULL) #define VNODEOP_SET(f) \ C_SYSINIT(f##init, SI_SUB_VFS, SI_ORDER_SECOND, vfs_add_vnodeops, &f); \ C_SYSUNINIT(f##uninit, SI_SUB_VFS, SI_ORDER_SECOND, vfs_rm_vnodeops, &f); /* * Global vnode data. */ extern struct vnode *rootvnode; /* root (i.e. "/") vnode */ extern int desiredvnodes; /* number of vnodes desired */ extern struct uma_zone *namei_zone; extern int prtactive; /* nonzero to call vprint() */ extern struct vattr va_null; /* predefined null vattr structure */ extern int vfs_ioopt; /* * Macro/function to check for client cache inconsistency w.r.t. leasing. */ #define LEASE_READ 0x1 /* Check lease for readers */ #define LEASE_WRITE 0x2 /* Check lease for modifiers */ extern void (*lease_updatetime)(int deltat); /* Requires interlock */ #define VSHOULDFREE(vp) \ (!((vp)->v_iflag & (VI_FREE|VI_DOOMED)) && \ !(vp)->v_holdcnt && !(vp)->v_usecount && \ (!(vp)->v_object || \ !((vp)->v_object->ref_count || (vp)->v_object->resident_page_count))) /* Requires interlock */ #define VMIGHTFREE(vp) \ (!((vp)->v_iflag & (VI_FREE|VI_DOOMED|VI_XLOCK)) && \ LIST_EMPTY(&(vp)->v_cache_src) && !(vp)->v_usecount) /* Requires interlock */ #define VSHOULDBUSY(vp) \ (((vp)->v_iflag & VI_FREE) && \ ((vp)->v_holdcnt || (vp)->v_usecount)) #define VI_LOCK(vp) mtx_lock(&(vp)->v_interlock) #define VI_TRYLOCK(vp) mtx_trylock(&(vp)->v_interlock) #define VI_UNLOCK(vp) mtx_unlock(&(vp)->v_interlock) #define VI_MTX(vp) (&(vp)->v_interlock) #endif /* _KERNEL */ /* * Mods for extensibility. */ /* * Flags for vdesc_flags: */ #define VDESC_MAX_VPS 16 /* Low order 16 flag bits are reserved for willrele flags for vp arguments. */ #define VDESC_VP0_WILLRELE 0x0001 #define VDESC_VP1_WILLRELE 0x0002 #define VDESC_VP2_WILLRELE 0x0004 #define VDESC_VP3_WILLRELE 0x0008 #define VDESC_NOMAP_VPP 0x0100 #define VDESC_VPP_WILLRELE 0x0200 /* * VDESC_NO_OFFSET is used to identify the end of the offset list * and in places where no such field exists. */ #define VDESC_NO_OFFSET -1 /* * This structure describes the vnode operation taking place. */ struct vnodeop_desc { int vdesc_offset; /* offset in vector,first for speed */ char *vdesc_name; /* a readable name for debugging */ int vdesc_flags; /* VDESC_* flags */ /* * These ops are used by bypass routines to map and locate arguments. * Creds and procs are not needed in bypass routines, but sometimes * they are useful to (for example) transport layers. * Nameidata is useful because it has a cred in it. */ int *vdesc_vp_offsets; /* list ended by VDESC_NO_OFFSET */ int vdesc_vpp_offset; /* return vpp location */ int vdesc_cred_offset; /* cred location, if any */ int vdesc_thread_offset; /* thread location, if any */ int vdesc_componentname_offset; /* if any */ /* * Finally, we've got a list of private data (about each operation) * for each transport layer. (Support to manage this list is not * yet part of BSD.) */ caddr_t *vdesc_transports; }; #ifdef _KERNEL /* * A list of all the operation descs. */ extern struct vnodeop_desc *vnodeop_descs[]; /* * Interlock for scanning list of vnodes attached to a mountpoint */ extern struct mtx mntvnode_mtx; /* * This macro is very helpful in defining those offsets in the vdesc struct. * * This is stolen from X11R4. I ignored all the fancy stuff for * Crays, so if you decide to port this to such a serious machine, * you might want to consult Intrinsic.h's XtOffset{,Of,To}. */ #define VOPARG_OFFSET(p_type,field) \ ((int) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) #define VOPARG_OFFSETOF(s_type,field) \ VOPARG_OFFSET(s_type*,field) #define VOPARG_OFFSETTO(S_TYPE,S_OFFSET,STRUCT_P) \ ((S_TYPE)(((char*)(STRUCT_P))+(S_OFFSET))) /* * This structure is used to configure the new vnodeops vector. */ struct vnodeopv_entry_desc { struct vnodeop_desc *opve_op; /* which operation this is */ vop_t *opve_impl; /* code implementing this operation */ }; struct vnodeopv_desc { /* ptr to the ptr to the vector where op should go */ vop_t ***opv_desc_vector_p; struct vnodeopv_entry_desc *opv_desc_ops; /* null terminated list */ }; /* * A generic structure. * This can be used by bypass routines to identify generic arguments. */ struct vop_generic_args { struct vnodeop_desc *a_desc; /* other random data follows, presumably */ }; /* * Support code to aid in debugging VFS locking problems. Not totally * reliable since if the thread sleeps between changing the lock * state and checking it with the assert, some other thread could * change the state. They are good enough for debugging a single * filesystem using a single-threaded test. */ void assert_vi_locked(struct vnode *vp, char *str); void assert_vi_unlocked(struct vnode *vp, char *str); void assert_vop_unlocked(struct vnode *vp, char *str); void assert_vop_locked(struct vnode *vp, char *str); void assert_vop_slocked(struct vnode *vp, char *str); void assert_vop_elocked(struct vnode *vp, char *str); void assert_vop_elocked_other(struct vnode *vp, char *str); /* These are called from within the actuall VOPS */ void vop_rename_pre(void *a); void vop_strategy_pre(void *a); void vop_lookup_pre(void *a); void vop_lookup_post(void *a, int rc); void vop_lock_pre(void *a); void vop_lock_post(void *a, int rc); void vop_unlock_pre(void *a); void vop_unlock_post(void *a, int rc); #ifdef DEBUG_VFS_LOCKS #define ASSERT_VI_LOCKED(vp, str) assert_vi_locked((vp), (str)) #define ASSERT_VI_UNLOCKED(vp, str) assert_vi_unlocked((vp), (str)) #define ASSERT_VOP_LOCKED(vp, str) assert_vop_locked((vp), (str)) #define ASSERT_VOP_UNLOCKED(vp, str) assert_vop_unlocked((vp), (str)) #define ASSERT_VOP_ELOCKED(vp, str) assert_vop_elocked((vp), (str)) #define ASSERT_VOP_ELOCKED_OTHER(vp, str) assert_vop_locked_other((vp), (str)) #define ASSERT_VOP_SLOCKED(vp, str) assert_vop_slocked((vp), (str)) #else #define ASSERT_VOP_LOCKED(vp, str) do { } while(0) #define ASSERT_VOP_UNLOCKED(vp, str) do { } while(0) #define ASSERT_VOP_ELOCKED(vp, str) do { } while(0) #define ASSERT_VOP_ELOCKED_OTHER(vp, str) do { } while(0) #define ASSERT_VOP_SLOCKED(vp, str) do { } while(0) #define ASSERT_VI_UNLOCKED(vp, str) do { } while(0) #define ASSERT_VI_LOCKED(vp, str) do { } while(0) #endif /* * VOCALL calls an op given an ops vector. We break it out because BSD's * vclean changes the ops vector and then wants to call ops with the old * vector. */ #define VOCALL(OPSV,OFF,AP) (( *((OPSV)[(OFF)])) (AP)) /* * This call works for vnodes in the kernel. */ #define VCALL(VP,OFF,AP) VOCALL((VP)->v_op,(OFF),(AP)) #define VDESC(OP) (& __CONCAT(OP,_desc)) #define VOFFSET(OP) (VDESC(OP)->vdesc_offset) /* * VMIO support inline */ extern int vmiodirenable; static __inline int vn_canvmio(struct vnode *vp) { if (vp && (vp->v_type == VREG || (vmiodirenable && vp->v_type == VDIR))) return(TRUE); return(FALSE); } /* * Finally, include the default set of vnode operations. */ #include "vnode_if.h" /* * Public vnode manipulation functions. */ struct componentname; struct file; struct mount; struct nameidata; struct ostat; struct thread; struct proc; struct stat; struct nstat; struct ucred; struct uio; struct vattr; struct vnode; extern int (*lease_check_hook)(struct vop_lease_args *); extern int (*softdep_fsync_hook)(struct vnode *); extern int (*softdep_process_worklist_hook)(struct mount *); struct vnode *addaliasu(struct vnode *vp, udev_t nvp_rdev); int bdevvp(dev_t dev, struct vnode **vpp); /* cache_* may belong in namei.h. */ void cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp); int cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp); void cache_purge(struct vnode *vp); void cache_purgevfs(struct mount *mp); int cache_leaf_test(struct vnode *vp); void cvtstat(struct stat *st, struct ostat *ost); void cvtnstat(struct stat *sb, struct nstat *nsb); int getnewvnode(const char *tag, struct mount *mp, vop_t **vops, struct vnode **vpp); int lease_check(struct vop_lease_args *ap); int spec_vnoperate(struct vop_generic_args *); int speedup_syncer(void); #define textvp_fullpath(p, rb, rfb) \ vn_fullpath(FIRST_THREAD_IN_PROC(p), (p)->p_textvp, rb, rfb) int vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf); int vaccess(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid, mode_t acc_mode, struct ucred *cred, int *privused); int vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, struct acl *acl, mode_t acc_mode, struct ucred *cred, int *privused); void vattr_null(struct vattr *vap); int vcount(struct vnode *vp); void vdrop(struct vnode *); void vdropl(struct vnode *); int vfinddev(dev_t dev, enum vtype type, struct vnode **vpp); void vfs_add_vnodeops(const void *); void vfs_rm_vnodeops(const void *); int vflush(struct mount *mp, int rootrefs, int flags); int vget(struct vnode *vp, int lockflag, struct thread *td); void vgone(struct vnode *vp); void vgonel(struct vnode *vp, struct thread *td); void vhold(struct vnode *); void vholdl(struct vnode *); int vinvalbuf(struct vnode *vp, int save, struct ucred *cred, struct thread *td, int slpflag, int slptimeo); int vtruncbuf(struct vnode *vp, struct ucred *cred, struct thread *td, off_t length, int blksize); void vprint(char *label, struct vnode *vp); int vrecycle(struct vnode *vp, struct mtx *inter_lkp, struct thread *td); int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td); void vn_finished_write(struct mount *mp); int vn_isdisk(struct vnode *vp, int *errp); int vn_lock(struct vnode *vp, int flags, struct thread *td); #ifdef DEBUG_LOCKS int debug_vn_lock(struct vnode *vp, int flags, struct thread *p, const char *filename, int line); #define vn_lock(vp,flags,p) debug_vn_lock(vp,flags,p,__FILE__,__LINE__) #endif int vn_open(struct nameidata *ndp, int *flagp, int cmode); int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, struct ucred *cred); void vn_pollevent(struct vnode *vp, int events); void vn_pollgone(struct vnode *vp); int vn_pollrecord(struct vnode *vp, struct thread *p, int events); int vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *active_cred, struct ucred *file_cred, int *aresid, struct thread *td); int vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *active_cred, struct ucred *file_cred, int *aresid, struct thread *td); int vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, struct ucred *file_cred, struct thread *td); int vn_start_write(struct vnode *vp, struct mount **mpp, int flags); dev_t vn_todev(struct vnode *vp); int vn_write_suspend_wait(struct vnode *vp, struct mount *mp, int flags); int vn_writechk(struct vnode *vp); int vn_extattr_get(struct vnode *vp, int ioflg, int attrnamespace, const char *attrname, int *buflen, char *buf, struct thread *td); int vn_extattr_set(struct vnode *vp, int ioflg, int attrnamespace, const char *attrname, int buflen, char *buf, struct thread *td); int vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace, const char *attrname, struct thread *td); int vfs_cache_lookup(struct vop_lookup_args *ap); int vfs_object_create(struct vnode *vp, struct thread *td, struct ucred *cred); void vfs_timestamp(struct timespec *); void vfs_write_resume(struct mount *mp); void vfs_write_suspend(struct mount *mp); int vop_stdbmap(struct vop_bmap_args *); int vop_stdgetwritemount(struct vop_getwritemount_args *); int vop_stdgetpages(struct vop_getpages_args *); int vop_stdinactive(struct vop_inactive_args *); int vop_stdislocked(struct vop_islocked_args *); int vop_stdlock(struct vop_lock_args *); int vop_stdputpages(struct vop_putpages_args *); int vop_stdunlock(struct vop_unlock_args *); int vop_noislocked(struct vop_islocked_args *); int vop_nolock(struct vop_lock_args *); int vop_nopoll(struct vop_poll_args *); int vop_nounlock(struct vop_unlock_args *); int vop_stdpathconf(struct vop_pathconf_args *); int vop_stdpoll(struct vop_poll_args *); int vop_revoke(struct vop_revoke_args *); int vop_sharedlock(struct vop_lock_args *); int vop_eopnotsupp(struct vop_generic_args *ap); int vop_ebadf(struct vop_generic_args *ap); int vop_einval(struct vop_generic_args *ap); int vop_enotty(struct vop_generic_args *ap); int vop_defaultop(struct vop_generic_args *ap); int vop_null(struct vop_generic_args *ap); int vop_panic(struct vop_generic_args *ap); int vop_stdcreatevobject(struct vop_createvobject_args *ap); int vop_stddestroyvobject(struct vop_destroyvobject_args *ap); int vop_stdgetvobject(struct vop_getvobject_args *ap); void vfree(struct vnode *); void vput(struct vnode *vp); void vrele(struct vnode *vp); void vref(struct vnode *vp); int vrefcnt(struct vnode *vp); void vbusy(struct vnode *vp); void v_addpollinfo(struct vnode *vp); extern vop_t **default_vnodeop_p; extern vop_t **spec_vnodeop_p; extern vop_t **dead_vnodeop_p; #endif /* _KERNEL */ #endif /* !_SYS_VNODE_H_ */ diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c index 38736ff53d88..eb81388e69bb 100644 --- a/usr.bin/fstat/fstat.c +++ b/usr.bin/fstat/fstat.c @@ -1,939 +1,939 @@ /*- * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _KERNEL #include #include #include #include #include #include #undef _KERNEL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fstat.h" #define TEXT -1 #define CDIR -2 #define RDIR -3 #define TRACE -4 #define MMAP -5 DEVS *devs; #ifdef notdef struct nlist nl[] = { { "" }, }; #endif int fsflg, /* show files on same filesystem as file(s) argument */ pflg, /* show files open by a particular pid */ uflg; /* show files open by a particular (effective) user */ int checkfile; /* true if restricting to particular files or filesystems */ int nflg; /* (numerical) display f.s. and rdev as dev_t */ int vflg; /* display errors in locating kernel data objects etc... */ int mflg; /* include memory-mapped files */ struct file **ofiles; /* buffer of pointers to file structures */ int maxfiles; #define ALLOC_OFILES(d) \ if ((d) > maxfiles) { \ free(ofiles); \ ofiles = malloc((d) * sizeof(struct file *)); \ if (ofiles == NULL) { \ err(1, NULL); \ } \ maxfiles = (d); \ } char *memf, *nlistf; kvm_t *kd; static void fstat_kvm(int, int); static void fstat_sysctl(int, int); void dofiles(struct kinfo_proc *kp); void dommap(struct kinfo_proc *kp); void vtrans(struct vnode *vp, int i, int flag); int ufs_filestat(struct vnode *vp, struct filestat *fsp); int nfs_filestat(struct vnode *vp, struct filestat *fsp); int devfs_filestat(struct vnode *vp, struct filestat *fsp); char *getmnton(struct mount *m); void pipetrans(struct pipe *pi, int i, int flag); void socktrans(struct socket *sock, int i); void getinetproto(int number); int getfname(const char *filename); void usage(void); int main(argc, argv) int argc; char **argv; { struct passwd *passwd; int arg, ch, what; arg = 0; what = KERN_PROC_ALL; nlistf = memf = NULL; while ((ch = getopt(argc, argv, "fmnp:u:vN:M:")) != -1) switch((char)ch) { case 'f': fsflg = 1; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'm': mflg = 1; break; case 'n': nflg = 1; break; case 'p': if (pflg++) usage(); if (!isdigit(*optarg)) { warnx("-p requires a process id"); usage(); } what = KERN_PROC_PID; arg = atoi(optarg); break; case 'u': if (uflg++) usage(); if (!(passwd = getpwnam(optarg))) errx(1, "%s: unknown uid", optarg); what = KERN_PROC_UID; arg = passwd->pw_uid; break; case 'v': vflg = 1; break; case '?': default: usage(); } if (*(argv += optind)) { for (; *argv; ++argv) { if (getfname(*argv)) checkfile = 1; } if (!checkfile) /* file(s) specified, but none accessable */ exit(1); } if (fsflg && !checkfile) { /* -f with no files means use wd */ if (getfname(".") == 0) exit(1); checkfile = 1; } if (memf != NULL) fstat_kvm(what, arg); else fstat_sysctl(what, arg); exit(0); } static void print_header(void) { if (nflg) printf("%s", "USER CMD PID FD DEV INUM MODE SZ|DV R/W"); else printf("%s", "USER CMD PID FD MOUNT INUM MODE SZ|DV R/W"); if (checkfile && fsflg == 0) printf(" NAME\n"); else putchar('\n'); } static void fstat_kvm(int what, int arg) { struct kinfo_proc *p, *plast; char buf[_POSIX2_LINE_MAX]; int cnt; ALLOC_OFILES(256); /* reserve space for file pointers */ /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ if (nlistf != NULL || memf != NULL) setgid(getgid()); if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) errx(1, "%s", buf); setgid(getgid()); #ifdef notdef if (kvm_nlist(kd, nl) != 0) errx(1, "no namelist: %s", kvm_geterr(kd)); #endif if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) errx(1, "%s", kvm_geterr(kd)); for (plast = &p[cnt]; p < plast; ++p) { if (p->ki_stat == SZOMB) continue; dofiles(p); if (mflg) dommap(p); } } static void fstat_sysctl(int what, int arg) { /* not yet implemented */ fstat_kvm(what, arg); } const char *Uname, *Comm; int Pid; #define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ switch(i) { \ case TEXT: \ printf(" text"); \ break; \ case CDIR: \ printf(" wd"); \ break; \ case RDIR: \ printf(" root"); \ break; \ case TRACE: \ printf(" tr"); \ break; \ case MMAP: \ printf(" mmap"); \ break; \ default: \ printf(" %4d", i); \ break; \ } /* * print open files attributed to this process */ void dofiles(kp) struct kinfo_proc *kp; { int i; struct file file; struct filedesc0 filed0; #define filed filed0.fd_fd Uname = user_from_uid(kp->ki_uid, 0); Pid = kp->ki_pid; Comm = kp->ki_comm; if (kp->ki_fd == NULL) return; if (!KVM_READ(kp->ki_fd, &filed0, sizeof (filed0))) { dprintf(stderr, "can't read filedesc at %p for pid %d\n", (void *)kp->ki_fd, Pid); return; } /* * root directory vnode, if one */ if (filed.fd_rdir) vtrans(filed.fd_rdir, RDIR, FREAD); /* * current working directory vnode */ vtrans(filed.fd_cdir, CDIR, FREAD); /* * ktrace vnode, if one */ if (kp->ki_tracep) vtrans(kp->ki_tracep, TRACE, FREAD|FWRITE); /* * text vnode, if one */ if (kp->ki_textvp) vtrans(kp->ki_textvp, TEXT, FREAD); /* * open files */ #define FPSIZE (sizeof (struct file *)) ALLOC_OFILES(filed.fd_lastfile+1); if (filed.fd_nfiles > NDFILE) { if (!KVM_READ(filed.fd_ofiles, ofiles, (filed.fd_lastfile+1) * FPSIZE)) { dprintf(stderr, "can't read file structures at %p for pid %d\n", (void *)filed.fd_ofiles, Pid); return; } } else bcopy(filed0.fd_dfiles, ofiles, (filed.fd_lastfile+1) * FPSIZE); for (i = 0; i <= filed.fd_lastfile; i++) { if (ofiles[i] == NULL) continue; if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) { dprintf(stderr, "can't read file %d at %p for pid %d\n", i, (void *)ofiles[i], Pid); continue; } if (file.f_type == DTYPE_VNODE) vtrans((struct vnode *)file.f_data, i, file.f_flag); else if (file.f_type == DTYPE_SOCKET) { if (checkfile == 0) socktrans((struct socket *)file.f_data, i); } #ifdef DTYPE_PIPE else if (file.f_type == DTYPE_PIPE) { if (checkfile == 0) pipetrans((struct pipe *)file.f_data, i, file.f_flag); } #endif #ifdef DTYPE_FIFO else if (file.f_type == DTYPE_FIFO) { if (checkfile == 0) vtrans((struct vnode *)file.f_data, i, file.f_flag); } #endif else { dprintf(stderr, "unknown file type %d for file %d of pid %d\n", file.f_type, i, Pid); } } } void dommap(kp) struct kinfo_proc *kp; { vm_map_t map; struct vmspace vmspace; struct vm_map_entry entry; vm_map_entry_t entryp; struct vm_object object; vm_object_t objp; int prot, fflags; if (!KVM_READ(kp->ki_vmspace, &vmspace, sizeof(vmspace))) { dprintf(stderr, "can't read vmspace at %p for pid %d\n", (void *)kp->ki_vmspace, Pid); return; } map = &vmspace.vm_map; for (entryp = map->header.next; entryp != &kp->ki_vmspace->vm_map.header; entryp = entry.next) { if (!KVM_READ(entryp, &entry, sizeof(entry))) { dprintf(stderr, "can't read vm_map_entry at %p for pid %d\n", (void *)entryp, Pid); return; } if (entry.eflags & MAP_ENTRY_IS_SUB_MAP) continue; if ((objp = entry.object.vm_object) == NULL) continue; for (; objp; objp = object.backing_object) { if (!KVM_READ(objp, &object, sizeof(object))) { dprintf(stderr, "can't read vm_object at %p for pid %d\n", (void *)objp, Pid); return; } } prot = entry.protection; fflags = (prot & VM_PROT_READ ? FREAD : 0) | (prot & VM_PROT_WRITE ? FWRITE : 0); switch (object.type) { case OBJT_VNODE: vtrans((struct vnode *)object.handle, MMAP, fflags); break; default: break; } } } void vtrans(vp, i, flag) struct vnode *vp; int i; int flag; { struct vnode vn; struct filestat fst; char rw[3], mode[15], tagstr[12], *tagptr; const char *badtype, *filename; filename = badtype = NULL; if (!KVM_READ(vp, &vn, sizeof (struct vnode))) { dprintf(stderr, "can't read vnode at %p for pid %d\n", (void *)vp, Pid); return; } if (!KVM_READ(&vp->v_tag, &tagptr, sizeof tagptr) || !KVM_READ(tagptr, tagstr, sizeof tagstr)) { dprintf(stderr, "can't read v_tag at %p for pid %d\n", (void *)vp, Pid); return; } tagstr[sizeof(tagstr) - 1] = '\0'; if (vn.v_type == VNON) badtype = "none"; else if (vn.v_type == VBAD) badtype = "bad"; else { if (!strcmp("ufs", tagstr)) { if (!ufs_filestat(&vn, &fst)) badtype = "error"; } else if (!strcmp("devfs", tagstr)) { if (!devfs_filestat(&vn, &fst)) badtype = "error"; } else if (!strcmp("nfs", tagstr)) { if (!nfs_filestat(&vn, &fst)) badtype = "error"; } else if (!strcmp("msdosfs", tagstr)) { if (!msdosfs_filestat(&vn, &fst)) badtype = "error"; } else if (!strcmp("isofs", tagstr)) { if (!isofs_filestat(&vn, &fst)) badtype = "error"; } else { static char unknown[32]; snprintf(unknown, sizeof unknown, "?(%s)", tagstr); badtype = unknown; } } if (checkfile) { int fsmatch = 0; DEVS *d; if (badtype) return; for (d = devs; d != NULL; d = d->next) if (d->fsid == fst.fsid) { fsmatch = 1; if (d->ino == fst.fileid) { filename = d->name; break; } } if (fsmatch == 0 || (filename == NULL && fsflg == 0)) return; } PREFIX(i); if (badtype) { (void)printf(" - - %10s -\n", badtype); return; } if (nflg) (void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid)); else (void)printf(" %-8s", getmnton(vn.v_mount)); if (nflg) (void)sprintf(mode, "%o", fst.mode); else strmode(fst.mode, mode); (void)printf(" %6ld %10s", fst.fileid, mode); switch (vn.v_type) { case VBLK: case VCHR: { char *name; if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ? S_IFCHR : S_IFBLK)) == NULL)) printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev)); else printf(" %6s", name); break; } default: printf(" %6lu", fst.size); } rw[0] = '\0'; if (flag & FREAD) strcat(rw, "r"); if (flag & FWRITE) strcat(rw, "w"); printf(" %2s", rw); if (filename && !fsflg) printf(" %s", filename); putchar('\n'); } int ufs_filestat(vp, fsp) struct vnode *vp; struct filestat *fsp; { struct inode inode; if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { dprintf(stderr, "can't read inode at %p for pid %d\n", (void *)VTOI(vp), Pid); return 0; } /* * The st_dev from stat(2) is a udev_t. These kernel structures * contain dev_t structures. We need to convert to udev to make * comparisons */ fsp->fsid = dev2udev(inode.i_dev); fsp->fileid = (long)inode.i_number; fsp->mode = (mode_t)inode.i_mode; fsp->size = (u_long)inode.i_size; #if should_be_but_is_hard fsp->rdev = inode.i_rdev; #else fsp->rdev = 0; #endif return 1; } int devfs_filestat(vp, fsp) struct vnode *vp; struct filestat *fsp; { struct devfs_dirent devfs_dirent; struct mount mount; struct vnode vnode; if (!KVM_READ(vp->v_data, &devfs_dirent, sizeof (devfs_dirent))) { dprintf(stderr, "can't read devfs_dirent at %p for pid %d\n", (void *)vp->v_data, Pid); return 0; } if (!KVM_READ(vp->v_mount, &mount, sizeof (mount))) { dprintf(stderr, "can't read mount at %p for pid %d\n", (void *)vp->v_mount, Pid); return 0; } if (!KVM_READ(devfs_dirent.de_vnode, &vnode, sizeof (vnode))) { dprintf(stderr, "can't read vnode at %p for pid %d\n", (void *)devfs_dirent.de_vnode, Pid); return 0; } fsp->fsid = (long)mount.mnt_stat.f_fsid.val[0]; fsp->fileid = devfs_dirent.de_inode; fsp->mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR; fsp->size = 0; fsp->rdev = dev2udev((dev_t)vnode.v_rdev); return 1; } int nfs_filestat(vp, fsp) struct vnode *vp; struct filestat *fsp; { struct nfsnode nfsnode; mode_t mode; if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { dprintf(stderr, "can't read nfsnode at %p for pid %d\n", (void *)VTONFS(vp), Pid); return 0; } fsp->fsid = nfsnode.n_vattr.va_fsid; fsp->fileid = nfsnode.n_vattr.va_fileid; fsp->size = nfsnode.n_size; fsp->rdev = nfsnode.n_vattr.va_rdev; mode = (mode_t)nfsnode.n_vattr.va_mode; switch (vp->v_type) { case VREG: mode |= S_IFREG; break; case VDIR: mode |= S_IFDIR; break; case VBLK: mode |= S_IFBLK; break; case VCHR: mode |= S_IFCHR; break; case VLNK: mode |= S_IFLNK; break; case VSOCK: mode |= S_IFSOCK; break; case VFIFO: mode |= S_IFIFO; break; case VNON: case VBAD: return 0; }; fsp->mode = mode; return 1; } char * getmnton(m) struct mount *m; { static struct mount mount; static struct mtab { struct mtab *next; struct mount *m; char mntonname[MNAMELEN]; } *mhead = NULL; struct mtab *mt; for (mt = mhead; mt != NULL; mt = mt->next) if (m == mt->m) return (mt->mntonname); if (!KVM_READ(m, &mount, sizeof(struct mount))) { warnx("can't read mount table at %p", (void *)m); return (NULL); } if ((mt = malloc(sizeof (struct mtab))) == NULL) err(1, NULL); mt->m = m; bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); mt->next = mhead; mhead = mt; return (mt->mntonname); } void pipetrans(pi, i, flag) struct pipe *pi; int i; int flag; { struct pipe pip; char rw[3]; PREFIX(i); /* fill in socket */ if (!KVM_READ(pi, &pip, sizeof(struct pipe))) { dprintf(stderr, "can't read pipe at %p\n", (void *)pi); goto bad; } printf("* pipe %8lx <-> %8lx", (u_long)pi, (u_long)pip.pipe_peer); printf(" %6d", (int)pip.pipe_buffer.cnt); rw[0] = '\0'; if (flag & FREAD) strcat(rw, "r"); if (flag & FWRITE) strcat(rw, "w"); printf(" %2s", rw); putchar('\n'); return; bad: printf("* error\n"); } void socktrans(sock, i) struct socket *sock; int i; { static const char *stypename[] = { "unused", /* 0 */ "stream", /* 1 */ "dgram", /* 2 */ "raw", /* 3 */ "rdm", /* 4 */ "seqpak" /* 5 */ }; #define STYPEMAX 5 struct socket so; struct protosw proto; struct domain dom; struct inpcb inpcb; struct unpcb unpcb; int len; char dname[32]; PREFIX(i); /* fill in socket */ if (!KVM_READ(sock, &so, sizeof(struct socket))) { dprintf(stderr, "can't read sock at %p\n", (void *)sock); goto bad; } /* fill in protosw entry */ if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { dprintf(stderr, "can't read protosw at %p", (void *)so.so_proto); goto bad; } /* fill in domain */ if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { dprintf(stderr, "can't read domain at %p\n", (void *)proto.pr_domain); goto bad; } if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, sizeof(dname) - 1)) < 0) { dprintf(stderr, "can't read domain name at %p\n", (void *)dom.dom_name); dname[0] = '\0'; } else dname[len] = '\0'; if ((u_short)so.so_type > STYPEMAX) printf("* %s ?%d", dname, so.so_type); else printf("* %s %s", dname, stypename[so.so_type]); /* * protocol specific formatting * * Try to find interesting things to print. For tcp, the interesting * thing is the address of the tcpcb, for udp and others, just the * inpcb (socket pcb). For unix domain, its the address of the socket * pcb and the address of the connected pcb (if connected). Otherwise * just print the protocol number and address of the socket itself. * The idea is not to duplicate netstat, but to make available enough * information for further analysis. */ switch(dom.dom_family) { case AF_INET: case AF_INET6: getinetproto(proto.pr_protocol); if (proto.pr_protocol == IPPROTO_TCP ) { if (so.so_pcb) { if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, sizeof(struct inpcb)) != sizeof(struct inpcb)) { dprintf(stderr, "can't read inpcb at %p\n", (void *)so.so_pcb); goto bad; } printf(" %lx", (u_long)inpcb.inp_ppcb); } } else if (so.so_pcb) printf(" %lx", (u_long)so.so_pcb); break; case AF_UNIX: /* print address of pcb and connected pcb */ if (so.so_pcb) { printf(" %lx", (u_long)so.so_pcb); if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, sizeof(struct unpcb)) != sizeof(struct unpcb)){ dprintf(stderr, "can't read unpcb at %p\n", (void *)so.so_pcb); goto bad; } if (unpcb.unp_conn) { char shoconn[4], *cp; cp = shoconn; if (!(so.so_state & SS_CANTRCVMORE)) *cp++ = '<'; *cp++ = '-'; if (!(so.so_state & SS_CANTSENDMORE)) *cp++ = '>'; *cp = '\0'; printf(" %s %lx", shoconn, (u_long)unpcb.unp_conn); } } break; default: /* print protocol number and socket address */ printf(" %d %lx", proto.pr_protocol, (u_long)sock); } printf("\n"); return; bad: printf("* error\n"); } /* - * Read the specinfo structure in the kernel (as pointed to by a dev_t) + * Read the cdev structure in the kernel (as pointed to by a dev_t) * in order to work out the associated udev_t */ udev_t dev2udev(dev) dev_t dev; { - struct specinfo si; + struct cdev si; if (KVM_READ(dev, &si, sizeof si)) { return si.si_udev; } else { dprintf(stderr, "can't convert dev_t %x to a udev_t\n", dev); return -1; } } /* * getinetproto -- * print name of protocol number */ void getinetproto(number) int number; { static int isopen; struct protoent *pe; if (!isopen) setprotoent(++isopen); if ((pe = getprotobynumber(number)) != NULL) printf(" %s", pe->p_name); else printf(" %d", number); } int getfname(filename) const char *filename; { struct stat statbuf; DEVS *cur; if (stat(filename, &statbuf)) { warn("%s", filename); return(0); } if ((cur = malloc(sizeof(DEVS))) == NULL) err(1, NULL); cur->next = devs; devs = cur; cur->ino = statbuf.st_ino; cur->fsid = statbuf.st_dev; cur->name = filename; return(1); } void usage() { (void)fprintf(stderr, "usage: fstat [-fmnv] [-p pid] [-u user] [-N system] [-M core] [file ...]\n"); exit(1); }