-enum vtype iftovt_tab[16] = {
- VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
- VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
-};
-int vttoif_tab[9] = {
- 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT,
-};
-
-/*
- * Create a regular file
- */
-ufs_create(ndp, vap)
- struct nameidata *ndp;
- struct vattr *vap;
-{
- 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 */
-ufs_mknod(ndp, vap, cred)
- struct nameidata *ndp;
- struct ucred *cred;
- struct vattr *vap;
-{
- 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);
-}
-
-/*
- * Open called.
- *
- * Nothing to do.
- */
-/* ARGSUSED */
-ufs_open(vp, mode, cred)
- struct vnode *vp;
- int mode;
- struct ucred *cred;
-{
-
- return (0);
-}
-
-/*
- * Close called
- *
- * Update the times on the inode.
- */
-/* ARGSUSED */
-ufs_close(vp, fflag, cred)
- struct vnode *vp;
- int fflag;
- struct ucred *cred;
-{
- 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.
- */
-ufs_access(vp, mode, cred)
- struct vnode *vp;
- register int mode;
- struct ucred *cred;
-{
- 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 */
-ufs_getattr(vp, vap, cred)
- struct vnode *vp;
- register struct vattr *vap;
- struct ucred *cred;
-{
- 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
- */
-ufs_setattr(vp, vap, cred)
- register struct vnode *vp;
- register struct vattr *vap;
- register struct ucred *cred;
-{
- 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, cred))
- 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, &u.u_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, cred);
- if (vap->va_flags != VNOVAL) {
- if (cred->cr_uid != ip->i_uid &&
- (error = suser(cred, &u.u_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.
- */
-chmod1(vp, mode, cred)
- register struct vnode *vp;
- register int mode;
- struct ucred *cred;
-{
- register struct inode *ip = VTOI(vp);
- int error;
-
- if (cred->cr_uid != ip->i_uid &&
- (error = suser(cred, &u.u_acflag)))
- return (error);
- ip->i_mode &= ~07777;
- if (cred->cr_uid) {
- if (vp->v_type != VDIR)
- mode &= ~ISVTX;
- if (!groupmember(ip->i_gid, cred))
- mode &= ~ISGID;
- }
- 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.
- */
-chown1(vp, uid, gid, cred)
- register struct vnode *vp;
- uid_t uid;
- gid_t gid;
- struct ucred *cred;
-{
- register struct inode *ip = VTOI(vp);
- uid_t ouid;
- gid_t ogid;
- int error = 0;
-#ifdef QUOTA
- register int i;
- long change;
-#endif
-
- if (uid == (u_short)VNOVAL)
- uid = ip->i_uid;
- if (gid == (u_short)VNOVAL)
- gid = ip->i_gid;
- /*
- * If we don't own the file, are trying to change the owner
- * of the file, or are not a member of the target group,
- * the caller must be superuser or the call fails.
- */
- if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
- !groupmember((gid_t)gid, cred)) &&
- (error = suser(cred, &u.u_acflag)))
- return (error);
- ouid = ip->i_uid;
- ogid = ip->i_gid;
-#ifdef QUOTA
- if (error = getinoquota(ip))
- return (error);
- if (ouid == uid) {
- dqrele(vp, ip->i_dquot[USRQUOTA]);
- ip->i_dquot[USRQUOTA] = NODQUOT;
- }
- if (ogid == gid) {
- dqrele(vp, ip->i_dquot[GRPQUOTA]);
- ip->i_dquot[GRPQUOTA] = NODQUOT;
- }
- change = ip->i_blocks;
- (void) chkdq(ip, -change, cred, CHOWN);
- (void) chkiq(ip, -1, cred, CHOWN);
- for (i = 0; i < MAXQUOTAS; i++) {
- dqrele(vp, ip->i_dquot[i]);
- ip->i_dquot[i] = NODQUOT;
- }
-#endif
- ip->i_uid = uid;
- ip->i_gid = gid;
-#ifdef QUOTA
- if ((error = getinoquota(ip)) == 0) {
- if (ouid == uid) {
- dqrele(vp, ip->i_dquot[USRQUOTA]);
- ip->i_dquot[USRQUOTA] = NODQUOT;
- }
- if (ogid == gid) {
- dqrele(vp, ip->i_dquot[GRPQUOTA]);
- ip->i_dquot[GRPQUOTA] = NODQUOT;
- }
- if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
- if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
- goto good;
- else
- (void) chkdq(ip, -change, cred, CHOWN|FORCE);
- }
- for (i = 0; i < MAXQUOTAS; i++) {
- dqrele(vp, ip->i_dquot[i]);
- ip->i_dquot[i] = NODQUOT;
- }
- }
- ip->i_uid = ouid;
- ip->i_gid = ogid;
- if (getinoquota(ip) == 0) {
- if (ouid == uid) {
- dqrele(vp, ip->i_dquot[USRQUOTA]);
- ip->i_dquot[USRQUOTA] = NODQUOT;
- }
- if (ogid == gid) {
- dqrele(vp, ip->i_dquot[GRPQUOTA]);
- ip->i_dquot[GRPQUOTA] = NODQUOT;
- }
- (void) chkdq(ip, change, cred, FORCE|CHOWN);
- (void) chkiq(ip, 1, cred, FORCE|CHOWN);
- (void) getinoquota(ip);
- }
- return (error);
-good:
- if (getinoquota(ip))
- panic("chown: lost quota");
-#endif /* QUOTA */
- if (ouid != uid || ogid != gid)
- ip->i_flag |= ICHG;
- if (ouid != uid && cred->cr_uid != 0)
- ip->i_mode &= ~ISUID;
- if (ogid != gid && cred->cr_uid != 0)
- ip->i_mode &= ~ISGID;
- return (0);
-}
-