/* * symlink -- make a symbolic link */ int ufs_symlink(void *v) { struct vop_symlink_args *ap = v; struct vnode *vp, **vpp = ap->a_vpp; struct inode *ip; int len, error; error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); VN_KNOTE(ap->a_dvp, NOTE_WRITE); vp = *vpp; len = strlen(ap->a_target); if (len < vp->v_mount->mnt_maxsymlinklen) { ip = VTOI(vp); bcopy(ap->a_target, (char *)SHORTLINK(ip), len); DIP_ASSIGN(ip, size, len); ip->i_flag |= IN_CHANGE | IN_UPDATE; } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, NULL, curproc); vput(vp); return (error); }
/* * Mknod vnode call */ int ufs_mknod(void *v) { struct vop_mknod_args *ap = v; struct vattr *vap = ap->a_vap; struct vnode **vpp = ap->a_vpp; struct inode *ip; int error; if ((error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ap->a_dvp, vpp, ap->a_cnp)) != 0) return (error); VN_KNOTE(ap->a_dvp, NOTE_WRITE); ip = VTOI(*vpp); ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; if (vap->va_rdev != VNOVAL) { /* * Want to be able to use this to make badblock * inodes, so don't truncate the dev number. */ DIP_ASSIGN(ip, rdev, vap->va_rdev); } /* * Remove inode so that it will be reloaded by VFS_VGET and * checked to see if it is an alias of an existing entry in * the inode cache. */ vput(*vpp); (*vpp)->v_type = VNON; vgone(*vpp); *vpp = NULL; return (0); }
/* * Create a regular file */ int ufs_create(void *v) { struct vop_create_v3_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *ap = v; int error; struct vnode *dvp = ap->a_dvp; struct ufs_lookup_results *ulr; /* XXX should handle this material another way */ ulr = &VTOI(dvp)->i_crap; UFS_CHECK_CRAPCOUNTER(VTOI(dvp)); /* * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful * ufs_makeinode */ fstrans_start(dvp->v_mount, FSTRANS_SHARED); error = ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), dvp, ulr, ap->a_vpp, ap->a_cnp); if (error) { fstrans_done(dvp->v_mount); return (error); } UFS_WAPBL_END1(dvp->v_mount, dvp); fstrans_done(dvp->v_mount); VN_KNOTE(dvp, NOTE_WRITE); VOP_UNLOCK(*ap->a_vpp); return (0); }
/* * Create a regular file */ int ufs_create(void *v) { struct vop_create_args *ap = v; int error; error = ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), ap->a_dvp, ap->a_vpp, ap->a_cnp); if (error) return (error); VN_KNOTE(ap->a_dvp, NOTE_WRITE); return (0); }
/* ARGSUSED */ int ufs_mknod(void *v) { struct vop_mknod_v3_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *ap = v; struct vattr *vap; struct vnode **vpp; struct inode *ip; int error; struct mount *mp; ino_t ino; struct ufs_lookup_results *ulr; vap = ap->a_vap; vpp = ap->a_vpp; /* XXX should handle this material another way */ ulr = &VTOI(ap->a_dvp)->i_crap; UFS_CHECK_CRAPCOUNTER(VTOI(ap->a_dvp)); /* * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful * ufs_makeinode */ fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); if ((error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ap->a_dvp, ulr, vpp, ap->a_cnp)) != 0) goto out; VN_KNOTE(ap->a_dvp, NOTE_WRITE); ip = VTOI(*vpp); mp = (*vpp)->v_mount; ino = ip->i_number; ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; if (vap->va_rdev != VNOVAL) { struct ufsmount *ump = ip->i_ump; /* * Want to be able to use this to make badblock * inodes, so don't truncate the dev number. */ if (ump->um_fstype == UFS1) ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev, UFS_MPNEEDSWAP(ump)); else ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev, UFS_MPNEEDSWAP(ump)); } UFS_WAPBL_UPDATE(*vpp, NULL, NULL, 0); UFS_WAPBL_END1(ap->a_dvp->v_mount, ap->a_dvp); /* * Remove inode so that it will be reloaded by vcache_get and * checked to see if it is an alias of an existing entry in * the inode cache. */ (*vpp)->v_type = VNON; VOP_UNLOCK(*vpp); vgone(*vpp); error = vcache_get(mp, &ino, sizeof(ino), vpp); out: fstrans_done(ap->a_dvp->v_mount); if (error != 0) { *vpp = NULL; return (error); } return (0); }
/* * symlink -- make a symbolic link */ int ufs_symlink(void *v) { struct vop_symlink_v3_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; char *a_target; } */ *ap = v; struct vnode *vp, **vpp; struct inode *ip; int len, error; struct ufs_lookup_results *ulr; vpp = ap->a_vpp; /* XXX should handle this material another way */ ulr = &VTOI(ap->a_dvp)->i_crap; UFS_CHECK_CRAPCOUNTER(VTOI(ap->a_dvp)); /* * UFS_WAPBL_BEGIN1(dvp->v_mount, dvp) performed by successful * ufs_makeinode */ fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, ulr, vpp, ap->a_cnp); if (error) goto out; VN_KNOTE(ap->a_dvp, NOTE_WRITE); vp = *vpp; len = strlen(ap->a_target); ip = VTOI(vp); /* * This test is off by one. um_maxsymlinklen contains the * number of bytes available, and we aren't storing a \0, so * the test should properly be <=. However, it cannot be * changed as this would break compatibility with existing fs * images -- see the way ufs_readlink() works. */ if (len < ip->i_ump->um_maxsymlinklen) { memcpy((char *)SHORTLINK(ip), ap->a_target, len); ip->i_size = len; DIP_ASSIGN(ip, size, len); uvm_vnp_setsize(vp, ip->i_size); ip->i_flag |= IN_CHANGE | IN_UPDATE; if (vp->v_mount->mnt_flag & MNT_RELATIME) ip->i_flag |= IN_ACCESS; UFS_WAPBL_UPDATE(vp, NULL, NULL, 0); } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_JOURNALLOCKED, ap->a_cnp->cn_cred, NULL, NULL); UFS_WAPBL_END1(ap->a_dvp->v_mount, ap->a_dvp); VOP_UNLOCK(vp); if (error) vrele(vp); out: fstrans_done(ap->a_dvp->v_mount); return (error); }