- * @(#)lfs_vnops.c 7.65 (Berkeley) %G%
- */
-
-#include "param.h"
-#include "systm.h"
-#include "namei.h"
-#include "resourcevar.h"
-#include "kernel.h"
-#include "file.h"
-#include "stat.h"
-#include "buf.h"
-#include "proc.h"
-#include "conf.h"
-#include "mount.h"
-#include "vnode.h"
-#include "specdev.h"
-#include "fifo.h"
-#include "malloc.h"
-
-#include "lockf.h"
-#include "quota.h"
-#include "inode.h"
-#include "dir.h"
-#include "lfs.h"
-
-static int chmod1 __P((struct vnode *, int, struct proc *));
-static int chown1 __P((struct vnode *, uid_t, gid_t, struct proc *));
-static int maknode __P((int, struct nameidata *, struct inode **));
-
-/*
- * Create a regular file
- */
-lfs_create(ndp, vap, p)
- struct nameidata *ndp;
- struct vattr *vap;
- struct proc *p;
-{
- struct inode *ip;
- int error;
-
- if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
- return (error);
- ndp->ni_vp = ITOV(ip);
- return (0);
-}
-
-/*
- * Mknod vnode call
- */
-/* ARGSUSED */
-lfs_mknod(ndp, vap, cred, p)
- struct nameidata *ndp;
- struct ucred *cred;
- struct vattr *vap;
- struct proc *p;
-{
- register struct vnode *vp;
- struct inode *ip;
- int error;
-
- if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
- return (error);
- ip->i_flag |= IACC|IUPD|ICHG;
- if (vap->va_rdev != VNOVAL) {
- /*
- * Want to be able to use this to make badblock
- * inodes, so don't truncate the dev number.
- */
- ip->i_rdev = vap->va_rdev;
- }
- /*
- * Remove inode so that it will be reloaded by iget and
- * checked to see if it is an alias of an existing entry
- * in the inode cache.
- */
- vp = ITOV(ip);
- vput(vp);
- vp->v_type = VNON;
- vgone(vp);
- return (0);
-}
-
-/*
- * Close called
- *
- * Update the times on the inode.
- */
-/* ARGSUSED */
-lfs_close(vp, fflag, cred, p)
- struct vnode *vp;
- int fflag;
- struct ucred *cred;
- struct proc *p;
-{
- register struct inode *ip = VTOI(vp);
-
- if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
- ITIMES(ip, &time, &time);
- return (0);
-}
-
-/*
- * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
- * The mode is shifted to select the owner/group/other fields. The
- * super user is granted all permissions.
- */
-lfs_access(vp, mode, cred, p)
- struct vnode *vp;
- register int mode;
- struct ucred *cred;
- struct proc *p;
-{
- register struct inode *ip = VTOI(vp);
- register gid_t *gp;
- int i, error;
-
-#ifdef DIAGNOSTIC
- if (!VOP_ISLOCKED(vp)) {
- vprint("ufs_access: not locked", vp);
- panic("ufs_access: not locked");
- }
-#endif
-#ifdef QUOTA
- if (mode & VWRITE) {
- switch (vp->v_type) {
- case VREG: case VDIR: case VLNK:
- if (error = getinoquota(ip))
- return (error);
- }
- }
-#endif /* QUOTA */
- /*
- * If you're the super-user, you always get access.
- */
- if (cred->cr_uid == 0)
- return (0);
- /*
- * Access check is based on only one of owner, group, public.
- * If not owner, then check group. If not a member of the
- * group, then check public access.
- */
- if (cred->cr_uid != ip->i_uid) {
- mode >>= 3;
- gp = cred->cr_groups;
- for (i = 0; i < cred->cr_ngroups; i++, gp++)
- if (ip->i_gid == *gp)
- goto found;
- mode >>= 3;
-found:
- ;
- }
- if ((ip->i_mode & mode) != 0)
- return (0);
- return (EACCES);
-}
-
-/* ARGSUSED */
-lfs_getattr(vp, vap, cred, p)
- struct vnode *vp;
- register struct vattr *vap;
- struct ucred *cred;
- struct proc *p;
-{
- register struct inode *ip = VTOI(vp);
-
- ITIMES(ip, &time, &time);
- /*
- * Copy from inode table
- */
- vap->va_fsid = ip->i_dev;
- vap->va_fileid = ip->i_number;
- vap->va_mode = ip->i_mode & ~IFMT;
- vap->va_nlink = ip->i_nlink;
- vap->va_uid = ip->i_uid;
- vap->va_gid = ip->i_gid;
- vap->va_rdev = (dev_t)ip->i_rdev;
-#ifdef tahoe
- vap->va_size = ip->i_size;
- vap->va_size_rsv = 0;
-#else
- vap->va_qsize = ip->i_din.di_qsize;
-#endif
- vap->va_atime.tv_sec = ip->i_atime;
- vap->va_atime.tv_usec = 0;
- vap->va_mtime.tv_sec = ip->i_mtime;
- vap->va_mtime.tv_usec = 0;
- vap->va_ctime.tv_sec = ip->i_ctime;
- vap->va_ctime.tv_usec = 0;
- vap->va_flags = ip->i_flags;
- vap->va_gen = ip->i_gen;
- /* this doesn't belong here */
- if (vp->v_type == VBLK)
- vap->va_blocksize = BLKDEV_IOSIZE;
- else if (vp->v_type == VCHR)
- vap->va_blocksize = MAXBSIZE;
- else
- vap->va_blocksize = ip->i_fs->fs_bsize;
- vap->va_bytes = dbtob(ip->i_blocks);
- vap->va_bytes_rsv = 0;
- vap->va_type = vp->v_type;
- return (0);
-}
-
-/*
- * Set attribute vnode op. called from several syscalls
- */
-lfs_setattr(vp, vap, cred, p)
- register struct vnode *vp;
- register struct vattr *vap;
- register struct ucred *cred;
- struct proc *p;
-{
- register struct inode *ip = VTOI(vp);
- int error = 0;
-
- /*
- * Check for unsetable attributes.
- */
- if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
- (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
- (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
- ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
- return (EINVAL);
- }
- /*
- * Go through the fields and update iff not VNOVAL.
- */
- if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL)
- if (error = chown1(vp, vap->va_uid, vap->va_gid, p))
- return (error);
- if (vap->va_size != VNOVAL) {
- if (vp->v_type == VDIR)
- return (EISDIR);
- if (error = itrunc(ip, vap->va_size, 0)) /* XXX IO_SYNC? */
- return (error);
- }
- if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
- if (cred->cr_uid != ip->i_uid &&
- (error = suser(cred, &p->p_acflag)))
- return (error);
- if (vap->va_atime.tv_sec != VNOVAL)
- ip->i_flag |= IACC;
- if (vap->va_mtime.tv_sec != VNOVAL)
- ip->i_flag |= IUPD;
- ip->i_flag |= ICHG;
- if (error = iupdat(ip, &vap->va_atime, &vap->va_mtime, 1))
- return (error);
- }
- if (vap->va_mode != (u_short)VNOVAL)
- error = chmod1(vp, (int)vap->va_mode, p);
- if (vap->va_flags != VNOVAL) {
- if (cred->cr_uid != ip->i_uid &&
- (error = suser(cred, &p->p_acflag)))
- return (error);
- if (cred->cr_uid == 0) {
- ip->i_flags = vap->va_flags;
- } else {
- ip->i_flags &= 0xffff0000;
- ip->i_flags |= (vap->va_flags & 0xffff);
- }
- ip->i_flag |= ICHG;
- }
- return (error);
-}
-
-/*
- * Change the mode on a file.
- * Inode must be locked before calling.
- */
-static int
-chmod1(vp, mode, p)
- register struct vnode *vp;
- register int mode;
- struct proc *p;
-{
- register struct ucred *cred = p->p_ucred;
- register struct inode *ip = VTOI(vp);
- int error;
-
- if (cred->cr_uid != ip->i_uid &&
- (error = suser(cred, &p->p_acflag)))
- return (error);
- if (cred->cr_uid) {
- if (vp->v_type != VDIR && (mode & ISVTX))
- return (EFTYPE);
- if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
- return (EPERM);
- }
- ip->i_mode &= ~07777;
- ip->i_mode |= mode & 07777;
- ip->i_flag |= ICHG;
- if ((vp->v_flag & VTEXT) && (ip->i_mode & ISVTX) == 0)
- (void) vnode_pager_uncache(vp);
- return (0);
-}
-
-/*
- * Perform chown operation on inode ip;
- * inode must be locked prior to call.
- */
-static int
-chown1(vp, uid, gid, p)
- register struct vnode *vp;
- uid_t uid;
- gid_t gid;
- struct proc *p;
-{
- register struct inode *ip = VTOI(vp);
- register struct ucred *cred = p->p_ucred;
- uid_t ouid;
- gid_t ogid;
- int error = 0;
-#ifdef QUOTA
- register int i;
- long change;
-#endif
+ * @(#)lfs_vnops.c 7.94 (Berkeley) %G%
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/resourcevar.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+
+#include <miscfs/specfs/specdev.h>
+#include <miscfs/fifofs/fifo.h>
+
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/ufs_extern.h>
+
+#include <ufs/lfs/lfs.h>
+#include <ufs/lfs/lfs_extern.h>
+
+/* Global vfs data structures for lfs. */
+int (**lfs_vnodeop_p)();
+struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
+ { &vop_default_desc, vn_default_error },
+ { &vop_lookup_desc, ufs_lookup }, /* lookup */
+ { &vop_create_desc, lfs_create }, /* create */
+ { &vop_mknod_desc, lfs_mknod }, /* mknod */
+ { &vop_open_desc, ufs_open }, /* open */
+ { &vop_close_desc, lfs_close }, /* close */
+ { &vop_access_desc, ufs_access }, /* access */
+ { &vop_getattr_desc, lfs_getattr }, /* getattr */
+ { &vop_setattr_desc, ufs_setattr }, /* setattr */
+ { &vop_read_desc, lfs_read }, /* read */
+ { &vop_write_desc, lfs_write }, /* write */
+ { &vop_ioctl_desc, ufs_ioctl }, /* ioctl */
+ { &vop_select_desc, ufs_select }, /* select */
+ { &vop_mmap_desc, ufs_mmap }, /* mmap */
+ { &vop_fsync_desc, lfs_fsync }, /* fsync */
+ { &vop_seek_desc, ufs_seek }, /* seek */
+ { &vop_remove_desc, lfs_remove }, /* remove */
+ { &vop_link_desc, lfs_link }, /* link */
+ { &vop_rename_desc, lfs_rename }, /* rename */
+ { &vop_mkdir_desc, lfs_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, lfs_rmdir }, /* rmdir */
+ { &vop_symlink_desc, lfs_symlink }, /* symlink */
+ { &vop_readdir_desc, ufs_readdir }, /* readdir */
+ { &vop_readlink_desc, ufs_readlink }, /* readlink */
+ { &vop_abortop_desc, ufs_abortop }, /* abortop */
+ { &vop_inactive_desc, lfs_inactive }, /* inactive */
+ { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */
+ { &vop_lock_desc, ufs_lock }, /* lock */
+ { &vop_unlock_desc, ufs_unlock }, /* unlock */
+ { &vop_bmap_desc, lfs_bmap }, /* bmap */
+ { &vop_strategy_desc, ufs_strategy }, /* strategy */
+ { &vop_print_desc, ufs_print }, /* print */
+ { &vop_islocked_desc, ufs_islocked }, /* islocked */
+ { &vop_advlock_desc, ufs_advlock }, /* advlock */
+ { &vop_blkatoff_desc, lfs_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, lfs_valloc }, /* valloc */
+ { &vop_vfree_desc, lfs_vfree }, /* vfree */
+ { &vop_truncate_desc, lfs_truncate }, /* truncate */
+ { &vop_update_desc, lfs_update }, /* update */
+ { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */
+ { (struct vnodeop_desc*)NULL, (int(*)())NULL }
+};
+struct vnodeopv_desc lfs_vnodeop_opv_desc =
+ { &lfs_vnodeop_p, lfs_vnodeop_entries };
+
+int (**lfs_specop_p)();
+struct vnodeopv_entry_desc lfs_specop_entries[] = {
+ { &vop_default_desc, vn_default_error },
+ { &vop_lookup_desc, spec_lookup }, /* lookup */
+ { &vop_create_desc, spec_create }, /* create */
+ { &vop_mknod_desc, spec_mknod }, /* mknod */
+ { &vop_open_desc, spec_open }, /* open */
+ { &vop_close_desc, ufsspec_close }, /* close */
+ { &vop_access_desc, ufs_access }, /* access */
+ { &vop_getattr_desc, lfs_getattr }, /* getattr */
+ { &vop_setattr_desc, ufs_setattr }, /* setattr */
+ { &vop_read_desc, ufsspec_read }, /* read */
+ { &vop_write_desc, ufsspec_write }, /* write */
+ { &vop_ioctl_desc, spec_ioctl }, /* ioctl */
+ { &vop_select_desc, spec_select }, /* select */
+ { &vop_mmap_desc, spec_mmap }, /* mmap */
+ { &vop_fsync_desc, spec_fsync }, /* fsync */
+ { &vop_seek_desc, spec_seek }, /* seek */
+ { &vop_remove_desc, spec_remove }, /* remove */
+ { &vop_link_desc, spec_link }, /* link */
+ { &vop_rename_desc, spec_rename }, /* rename */
+ { &vop_mkdir_desc, spec_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, spec_rmdir }, /* rmdir */
+ { &vop_symlink_desc, spec_symlink }, /* symlink */
+ { &vop_readdir_desc, spec_readdir }, /* readdir */
+ { &vop_readlink_desc, spec_readlink }, /* readlink */
+ { &vop_abortop_desc, spec_abortop }, /* abortop */
+ { &vop_inactive_desc, lfs_inactive }, /* inactive */
+ { &vop_reclaim_desc, ufs_reclaim }, /* reclaim */
+ { &vop_lock_desc, ufs_lock }, /* lock */
+ { &vop_unlock_desc, ufs_unlock }, /* unlock */
+ { &vop_bmap_desc, spec_bmap }, /* bmap */
+ { &vop_strategy_desc, spec_strategy }, /* strategy */
+ { &vop_print_desc, ufs_print }, /* print */
+ { &vop_islocked_desc, ufs_islocked }, /* islocked */
+ { &vop_advlock_desc, spec_advlock }, /* advlock */
+ { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, spec_valloc }, /* valloc */
+ { &vop_vfree_desc, lfs_vfree }, /* vfree */
+ { &vop_truncate_desc, spec_truncate }, /* truncate */
+ { &vop_update_desc, lfs_update }, /* update */
+ { &vop_bwrite_desc, lfs_bwrite }, /* bwrite */
+ { (struct vnodeop_desc*)NULL, (int(*)())NULL }
+};
+struct vnodeopv_desc lfs_specop_opv_desc =
+ { &lfs_specop_p, lfs_specop_entries };