-/*
- * 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);
- vp = ITOV(ip);
- if (vap->va_rdev) {
- /*
- * Want to be able to use this to make badblock
- * inodes, so don't truncate the dev number.
- */
- ip->i_rdev = vap->va_rdev;
- ip->i_flag |= IACC|IUPD|ICHG;
- }
- /*
- * 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.
- */
- iput(ip);
- 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_count > 1 && !(ip->i_flag & ILOCKED))
- ITIMES(ip, &time, &time);
- return (0);
-}
-
-ufs_access(vp, mode, cred)
- struct vnode *vp;
- int mode;
- struct ucred *cred;
-{
-
- return (iaccess(VTOI(vp), mode, cred));
-}
-
-/* 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;
- vap->va_size = ip->i_din.di_qsize.val[0];
- vap->va_size1 = ip->i_din.di_qsize.val[1];
- 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_bytes1 = -1;
- 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)
- xrele(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);
-#ifdef QUOTA
- register long change;
-#endif
- int error;
-
- 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);
-#ifdef QUOTA
- if (ip->i_uid == uid) /* this just speeds things a little */
- change = 0;
- else
- change = ip->i_blocks;
- (void) chkdq(ip, -change, 1);
- (void) chkiq(ip->i_dev, ip, ip->i_uid, 1);
- dqrele(ip->i_dquot);
-#endif
- if (ip->i_uid != uid && cred->cr_uid != 0)
- ip->i_mode &= ~ISUID;
- if (ip->i_gid != gid && cred->cr_uid != 0)
- ip->i_mode &= ~ISGID;
- ip->i_uid = uid;
- ip->i_gid = gid;
- ip->i_flag |= ICHG;
-#ifdef QUOTA
- ip->i_dquot = inoquota(ip);
- (void) chkdq(ip, change, 1);
- (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1);
- return (u.u_error); /* should == 0 ALWAYS !! */
-#else
- return (0);
-#endif
-}