Fix vop_link, vop_symlink, and vop_remove semantics in several ways:
* Change the argument names to vop_link so they actually make sense. * Implement vop_link and vop_symlink for all file systems, so they do proper cleanup. * Require the file system to decide whether or not linking and unlinking of directories is allowed, and disable it for all current file systems.
This commit is contained in:
parent
d6b5a89f90
commit
53fccab940
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: advnops.c,v 1.23 1996/02/01 00:13:47 jtc Exp $ */
|
||||
/* $NetBSD: advnops.c,v 1.24 1996/02/09 14:45:40 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Christian E. Hopps
|
||||
|
@ -326,6 +326,49 @@ reterr:
|
|||
return(error);
|
||||
}
|
||||
|
||||
int
|
||||
adosfs_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
adosfs_symlink(ap)
|
||||
struct vop_symlink_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode **a_vpp;
|
||||
struct componentname *a_cnp;
|
||||
struct vattr *a_vap;
|
||||
char *a_target;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
adosfs_abortop(ap)
|
||||
struct vop_abortop_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
|
||||
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* lock the anode
|
||||
*/
|
||||
|
@ -895,12 +938,10 @@ int lease_check __P((struct vop_lease_args *));
|
|||
#define adosfs_seek ((int (*) __P((struct vop_seek_args *)))adnullop)
|
||||
#define adosfs_vfree ((int (*) __P((struct vop_vfree_args *)))adnullop)
|
||||
|
||||
#define adosfs_abortop ((int (*) __P((struct vop_abortop_args *)))adenotsup)
|
||||
#define adosfs_advlock ((int (*) __P((struct vop_advlock_args *)))adenotsup)
|
||||
#define adosfs_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))adenotsup)
|
||||
#define adosfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))adenotsup)
|
||||
#define adosfs_create ((int (*) __P((struct vop_create_args *)))adenotsup)
|
||||
#define adosfs_link ((int (*) __P((struct vop_link_args *)))adenotsup)
|
||||
#define adosfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))adenotsup)
|
||||
#define adosfs_mknod ((int (*) __P((struct vop_mknod_args *)))adenotsup)
|
||||
#define adosfs_mmap ((int (*) __P((struct vop_mmap_args *)))adenotsup)
|
||||
|
@ -908,7 +949,6 @@ int lease_check __P((struct vop_lease_args *));
|
|||
#define adosfs_rename ((int (*) __P((struct vop_rename_args *)))adenotsup)
|
||||
#define adosfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))adenotsup)
|
||||
#define adosfs_setattr ((int (*) __P((struct vop_setattr_args *)))adenotsup)
|
||||
#define adosfs_symlink ((int (*) __P((struct vop_symlink_args *)))adenotsup)
|
||||
#define adosfs_truncate ((int (*) __P((struct vop_truncate_args *)))adenotsup)
|
||||
#define adosfs_update ((int (*) __P((struct vop_update_args *)))adenotsup)
|
||||
#define adosfs_valloc ((int (*) __P((struct vop_valloc_args *)))adenotsup)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: cd9660_vnops.c,v 1.26 1995/12/01 00:47:33 pk Exp $ */
|
||||
/* $NetBSD: cd9660_vnops.c,v 1.27 1996/02/09 14:45:43 mycroft Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994
|
||||
|
@ -743,6 +743,36 @@ cd9660_readlink(ap)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_symlink(ap)
|
||||
struct vop_symlink_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode **a_vpp;
|
||||
struct componentname *a_cnp;
|
||||
struct vattr *a_vap;
|
||||
char *a_target;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
|
||||
* done. If a buffer has been saved in anticipation of a CREATE, delete it.
|
||||
|
@ -754,6 +784,7 @@ cd9660_abortop(ap)
|
|||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
|
||||
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
|
||||
return (0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vfs_syscalls.c,v 1.65 1996/02/08 02:54:20 mycroft Exp $ */
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.66 1996/02/09 14:45:36 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
|
@ -947,30 +947,23 @@ sys_link(p, v, retval)
|
|||
if ((error = namei(&nd)) != 0)
|
||||
return (error);
|
||||
vp = nd.ni_vp;
|
||||
if (vp->v_type != VDIR ||
|
||||
(error = suser(p->p_ucred, &p->p_acflag)) == 0) {
|
||||
nd.ni_cnd.cn_nameiop = CREATE;
|
||||
nd.ni_cnd.cn_flags = LOCKPARENT;
|
||||
nd.ni_dirp = SCARG(uap, link);
|
||||
if ((error = namei(&nd)) == 0) {
|
||||
if (nd.ni_vp != NULL)
|
||||
error = EEXIST;
|
||||
if (!error) {
|
||||
VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
|
||||
LEASE_WRITE);
|
||||
VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
|
||||
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
|
||||
} else {
|
||||
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
|
||||
if (nd.ni_dvp == nd.ni_vp)
|
||||
vrele(nd.ni_dvp);
|
||||
else
|
||||
vput(nd.ni_dvp);
|
||||
if (nd.ni_vp)
|
||||
vrele(nd.ni_vp);
|
||||
}
|
||||
}
|
||||
NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
|
||||
if ((error = namei(&nd)) != 0)
|
||||
goto out;
|
||||
if (nd.ni_vp) {
|
||||
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
|
||||
if (nd.ni_dvp == nd.ni_vp)
|
||||
vrele(nd.ni_dvp);
|
||||
else
|
||||
vput(nd.ni_dvp);
|
||||
vrele(nd.ni_vp);
|
||||
error = EEXIST;
|
||||
goto out;
|
||||
}
|
||||
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
|
||||
VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
|
||||
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
|
||||
out:
|
||||
vrele(vp);
|
||||
return (error);
|
||||
}
|
||||
|
@ -1084,29 +1077,24 @@ sys_unlink(p, v, retval)
|
|||
VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
|
||||
VOP_LOCK(vp);
|
||||
|
||||
if (vp->v_type != VDIR ||
|
||||
(error = suser(p->p_ucred, &p->p_acflag)) == 0) {
|
||||
/*
|
||||
* The root of a mounted filesystem cannot be deleted.
|
||||
*/
|
||||
if (vp->v_flag & VROOT)
|
||||
error = EBUSY;
|
||||
else
|
||||
(void)vnode_pager_uncache(vp);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
|
||||
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
|
||||
} else {
|
||||
/*
|
||||
* The root of a mounted filesystem cannot be deleted.
|
||||
*/
|
||||
if (vp->v_flag & VROOT) {
|
||||
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
|
||||
if (nd.ni_dvp == vp)
|
||||
vrele(nd.ni_dvp);
|
||||
else
|
||||
vput(nd.ni_dvp);
|
||||
if (vp != NULLVP)
|
||||
vput(vp);
|
||||
vput(vp);
|
||||
error = EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
|
||||
(void)vnode_pager_uncache(vp);
|
||||
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
|
||||
out:
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: vnode_if.src,v 1.8 1994/12/14 18:58:43 mycroft Exp $
|
||||
# $NetBSD: vnode_if.src,v 1.9 1996/02/09 14:45:38 mycroft Exp $
|
||||
#
|
||||
# Copyright (c) 1992, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
|
@ -149,8 +149,8 @@ vop_remove {
|
|||
};
|
||||
|
||||
vop_link {
|
||||
IN WILLRELE struct vnode *vp;
|
||||
IN struct vnode *tdvp;
|
||||
IN WILLRELE struct vnode *dvp;
|
||||
IN struct vnode *vp;
|
||||
IN struct componentname *cnp;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fdesc_vnops.c,v 1.28 1996/02/01 00:31:05 jtc Exp $ */
|
||||
/* $NetBSD: fdesc_vnops.c,v 1.29 1996/02/09 14:45:46 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -845,6 +845,49 @@ fdesc_vfree(ap)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
fdesc_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
fdesc_symlink(ap)
|
||||
struct vop_symlink_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode **a_vpp;
|
||||
struct componentname *a_cnp;
|
||||
struct vattr *a_vap;
|
||||
char *a_target;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
fdesc_abortop(ap)
|
||||
struct vop_abortop_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
|
||||
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* /dev/fd vnode unsupported operation
|
||||
*/
|
||||
|
@ -884,12 +927,9 @@ fdesc_nullop()
|
|||
#define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
|
||||
#define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp)
|
||||
#define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp)
|
||||
#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp)
|
||||
#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp)
|
||||
#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp)
|
||||
#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp)
|
||||
#define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
|
||||
#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop)
|
||||
#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
|
||||
#define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kernfs_vnops.c,v 1.39 1995/10/09 14:25:02 mycroft Exp $ */
|
||||
/* $NetBSD: kernfs_vnops.c,v 1.40 1996/02/09 14:45:48 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -635,6 +635,49 @@ kernfs_vfree(ap)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
kernfs_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
kernfs_symlink(ap)
|
||||
struct vop_symlink_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode **a_vpp;
|
||||
struct componentname *a_cnp;
|
||||
struct vattr *a_vap;
|
||||
char *a_target;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
kernfs_abortop(ap)
|
||||
struct vop_abortop_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
|
||||
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* /dev/fd vnode unsupported operation
|
||||
*/
|
||||
|
@ -672,14 +715,11 @@ kernfs_nullop()
|
|||
#define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
|
||||
#define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
#define kernfs_remove ((int (*) __P((struct vop_remove_args *)))kernfs_enotsupp)
|
||||
#define kernfs_link ((int (*) __P((struct vop_link_args *)))kernfs_enotsupp)
|
||||
#define kernfs_rename ((int (*) __P((struct vop_rename_args *)))kernfs_enotsupp)
|
||||
#define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))kernfs_enotsupp)
|
||||
#define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))kernfs_enotsupp)
|
||||
#define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp)
|
||||
#define kernfs_readlink \
|
||||
((int (*) __P((struct vop_readlink_args *)))kernfs_enotsupp)
|
||||
#define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
|
||||
#define kernfs_lock ((int (*) __P((struct vop_lock_args *)))nullop)
|
||||
#define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
|
||||
#define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: portal_vnops.c,v 1.14 1995/10/07 06:28:55 mycroft Exp $ */
|
||||
/* $NetBSD: portal_vnops.c,v 1.15 1996/02/09 14:45:50 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -596,6 +596,48 @@ portal_vfree(ap)
|
|||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
portal_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
portal_symlink(ap)
|
||||
struct vop_symlink_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode **a_vpp;
|
||||
struct componentname *a_cnp;
|
||||
struct vattr *a_vap;
|
||||
char *a_target;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
portal_abortop(ap)
|
||||
struct vop_abortop_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
|
||||
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Portal vnode unsupported operation
|
||||
|
@ -640,15 +682,11 @@ portal_nullop()
|
|||
#define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
|
||||
#define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
|
||||
#define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
|
||||
#define portal_link ((int (*) __P((struct vop_link_args *)))portal_enotsupp)
|
||||
#define portal_rename ((int (*) __P((struct vop_rename_args *)))portal_enotsupp)
|
||||
#define portal_mkdir ((int (*) __P((struct vop_mkdir_args *)))portal_enotsupp)
|
||||
#define portal_rmdir ((int (*) __P((struct vop_rmdir_args *)))portal_enotsupp)
|
||||
#define portal_symlink \
|
||||
((int (*) __P((struct vop_symlink_args *)))portal_enotsupp)
|
||||
#define portal_readlink \
|
||||
((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
|
||||
#define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
|
||||
#define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop)
|
||||
#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
|
||||
#define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: procfs_vnops.c,v 1.35 1995/10/09 14:03:38 mycroft Exp $ */
|
||||
/* $NetBSD: procfs_vnops.c,v 1.36 1996/02/09 14:45:53 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1993 Jan-Simon Pendry
|
||||
|
@ -304,6 +304,36 @@ procfs_print(ap)
|
|||
pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
int
|
||||
procfs_symlink(ap)
|
||||
struct vop_symlink_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode **a_vpp;
|
||||
struct componentname *a_cnp;
|
||||
struct vattr *a_vap;
|
||||
char *a_target;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
/*
|
||||
* _abortop is called when operations such as
|
||||
* rename and create fail. this entry is responsible
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: union_vnops.c,v 1.25 1995/07/13 13:19:18 mycroft Exp $ */
|
||||
/* $NetBSD: union_vnops.c,v 1.26 1996/02/09 14:45:56 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993, 1994 The Regents of the University of California.
|
||||
|
@ -944,54 +944,55 @@ union_remove(ap)
|
|||
int
|
||||
union_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct vnode *a_tdvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
int error = 0;
|
||||
struct union_node *un;
|
||||
struct union_node *dun;
|
||||
struct vnode *dvp;
|
||||
struct vnode *vp;
|
||||
struct vnode *tdvp;
|
||||
|
||||
un = VTOUNION(ap->a_vp);
|
||||
dun = VTOUNION(ap->a_dvp);
|
||||
|
||||
if (ap->a_vp->v_op != ap->a_tdvp->v_op) {
|
||||
tdvp = ap->a_tdvp;
|
||||
if (ap->a_dvp->v_op != ap->a_vp->v_op) {
|
||||
vp = ap->a_vp;
|
||||
} else {
|
||||
struct union_node *tdun = VTOUNION(ap->a_tdvp);
|
||||
if (tdun->un_uppervp == NULLVP) {
|
||||
VOP_LOCK(ap->a_tdvp);
|
||||
if (un->un_uppervp == tdun->un_dirvp) {
|
||||
un->un_flags &= ~UN_ULOCK;
|
||||
VOP_UNLOCK(un->un_uppervp);
|
||||
struct union_node *un = VTOUNION(ap->a_vp);
|
||||
|
||||
if (un->un_uppervp == NULLVP) {
|
||||
VOP_LOCK(ap->a_vp);
|
||||
if (dun->un_uppervp == un->un_dirvp) {
|
||||
dun->un_flags &= ~UN_ULOCK;
|
||||
VOP_UNLOCK(dun->un_uppervp);
|
||||
}
|
||||
error = union_copyup(tdun, 1, ap->a_cnp->cn_cred,
|
||||
error = union_copyup(un, 1, ap->a_cnp->cn_cred,
|
||||
ap->a_cnp->cn_proc);
|
||||
if (un->un_uppervp == tdun->un_dirvp) {
|
||||
VOP_LOCK(un->un_uppervp);
|
||||
un->un_flags |= UN_ULOCK;
|
||||
if (dun->un_uppervp == un->un_dirvp) {
|
||||
VOP_LOCK(dun->un_uppervp);
|
||||
dun->un_flags |= UN_ULOCK;
|
||||
}
|
||||
VOP_UNLOCK(ap->a_tdvp);
|
||||
VOP_UNLOCK(ap->a_vp);
|
||||
}
|
||||
tdvp = tdun->un_uppervp;
|
||||
vp = un->un_uppervp;
|
||||
}
|
||||
|
||||
vp = un->un_uppervp;
|
||||
if (vp == NULLVP)
|
||||
dvp = dun->un_uppervp;
|
||||
if (dvp == NULLVP)
|
||||
error = EROFS;
|
||||
|
||||
if (error) {
|
||||
vput(ap->a_vp);
|
||||
vput(ap->a_dvp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
FIXUP(un);
|
||||
VREF(vp);
|
||||
un->un_flags |= UN_KLOCK;
|
||||
vput(ap->a_vp);
|
||||
FIXUP(dun);
|
||||
VREF(dvp);
|
||||
dun->un_flags |= UN_KLOCK;
|
||||
vput(ap->a_dvp);
|
||||
|
||||
return (VOP_LINK(vp, tdvp, ap->a_cnp));
|
||||
return (VOP_LINK(dvp, vp, ap->a_cnp));
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: msdosfs_vnops.c,v 1.44 1996/02/01 00:37:36 jtc Exp $ */
|
||||
/* $NetBSD: msdosfs_vnops.c,v 1.45 1996/02/09 14:45:59 mycroft Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1994, 1995 Wolfgang Solfrank.
|
||||
|
@ -772,14 +772,14 @@ msdosfs_remove(ap)
|
|||
int
|
||||
msdosfs_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct vnode *a_tdvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
|
||||
VOP_ABORTOP(ap->a_vp, ap->a_cnp);
|
||||
vput(ap->a_vp);
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
|
@ -1334,12 +1334,10 @@ msdosfs_symlink(ap)
|
|||
char *a_target;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *dvp = ap->a_dvp;
|
||||
register struct componentname *cnp = ap->a_cnp;
|
||||
|
||||
FREE(cnp->cn_pnbuf, M_NAMEI);
|
||||
vput(dvp);
|
||||
return (EINVAL);
|
||||
VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
|
||||
vput(ap->a_dvp);
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nfs_vnops.c,v 1.56 1996/02/01 00:41:19 jtc Exp $ */
|
||||
/* $NetBSD: nfs_vnops.c,v 1.57 1996/02/09 14:46:03 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
|
@ -1301,13 +1301,13 @@ nfs_renameit(sdvp, scnp, sp)
|
|||
int
|
||||
nfs_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct vnode *a_tdvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *dvp = ap->a_dvp;
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
register struct vnode *tdvp = ap->a_tdvp;
|
||||
register struct componentname *cnp = ap->a_cnp;
|
||||
register u_int32_t *tl;
|
||||
register caddr_t cp;
|
||||
|
@ -1316,12 +1316,12 @@ nfs_link(ap)
|
|||
int error = 0;
|
||||
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
|
||||
|
||||
if (vp->v_mount != tdvp->v_mount) {
|
||||
/*VOP_ABORTOP(vp, cnp);*/
|
||||
if (tdvp == vp)
|
||||
vrele(vp);
|
||||
if (dvp->v_mount != vp->v_mount) {
|
||||
/*VOP_ABORTOP(dvp, cnp);*/
|
||||
if (vp == dvp)
|
||||
vrele(dvp);
|
||||
else
|
||||
vput(vp);
|
||||
vput(dvp);
|
||||
return (EXDEV);
|
||||
}
|
||||
|
||||
|
@ -1330,21 +1330,21 @@ nfs_link(ap)
|
|||
* doesn't get "out of sync" with the server.
|
||||
* XXX There should be a better way!
|
||||
*/
|
||||
VOP_FSYNC(tdvp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
|
||||
VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
|
||||
|
||||
nfsstats.rpccnt[NFSPROC_LINK]++;
|
||||
nfsm_reqhead(tdvp, NFSPROC_LINK,
|
||||
nfsm_reqhead(vp, NFSPROC_LINK,
|
||||
NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen));
|
||||
nfsm_fhtom(tdvp);
|
||||
nfsm_fhtom(vp);
|
||||
nfsm_fhtom(dvp);
|
||||
nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
|
||||
nfsm_request(tdvp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
|
||||
nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
|
||||
nfsm_reqdone;
|
||||
FREE(cnp->cn_pnbuf, M_NAMEI);
|
||||
VTONFS(tdvp)->n_attrstamp = 0;
|
||||
VTONFS(vp)->n_flag |= NMODIFIED;
|
||||
VTONFS(vp)->n_attrstamp = 0;
|
||||
vrele(vp);
|
||||
VTONFS(dvp)->n_flag |= NMODIFIED;
|
||||
VTONFS(dvp)->n_attrstamp = 0;
|
||||
vrele(dvp);
|
||||
/*
|
||||
* Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: lfs_vnops.c,v 1.8 1996/02/01 00:07:51 jtc Exp $ */
|
||||
/* $NetBSD: lfs_vnops.c,v 1.9 1996/02/09 14:46:06 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986, 1989, 1991, 1993
|
||||
|
@ -370,17 +370,17 @@ lfs_rmdir(ap)
|
|||
int
|
||||
lfs_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct vnode *a_tdvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
int ret;
|
||||
|
||||
SET_DIROP(VTOI(ap->a_vp)->i_lfs);
|
||||
MARK_VNODE(ap->a_vp);
|
||||
SET_DIROP(VTOI(ap->a_dvp)->i_lfs);
|
||||
MARK_VNODE(ap->a_dvp);
|
||||
ret = ufs_link(ap);
|
||||
SET_ENDOP(VTOI(ap->a_vp)->i_lfs);
|
||||
SET_ENDOP(VTOI(ap->a_dvp)->i_lfs);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ufs_vnops.c,v 1.13 1996/02/07 17:01:25 jtc Exp $ */
|
||||
/* $NetBSD: ufs_vnops.c,v 1.14 1996/02/09 14:46:08 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
|
@ -594,6 +594,10 @@ ufs_remove(ap)
|
|||
register struct vnode *dvp = ap->a_dvp;
|
||||
int error;
|
||||
|
||||
if (vp->v_type == VDIR) {
|
||||
error = EISDIR;
|
||||
goto out;
|
||||
}
|
||||
ip = VTOI(vp);
|
||||
if ((ip->i_flags & (IMMUTABLE | APPEND)) ||
|
||||
(VTOI(dvp)->i_flags & APPEND)) {
|
||||
|
@ -619,13 +623,13 @@ out:
|
|||
int
|
||||
ufs_link(ap)
|
||||
struct vop_link_args /* {
|
||||
struct vnode *a_dvp;
|
||||
struct vnode *a_vp;
|
||||
struct vnode *a_tdvp;
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
register struct vnode *dvp = ap->a_dvp;
|
||||
register struct vnode *vp = ap->a_vp;
|
||||
register struct vnode *tdvp = ap->a_tdvp;
|
||||
register struct componentname *cnp = ap->a_cnp;
|
||||
register struct inode *ip;
|
||||
struct timeval tv;
|
||||
|
@ -635,42 +639,47 @@ ufs_link(ap)
|
|||
if ((cnp->cn_flags & HASBUF) == 0)
|
||||
panic("ufs_link: no name");
|
||||
#endif
|
||||
if (vp->v_mount != tdvp->v_mount) {
|
||||
VOP_ABORTOP(vp, cnp);
|
||||
if (vp->v_type == VDIR) {
|
||||
VOP_ABORTOP(dvp, cnp);
|
||||
error = EISDIR;
|
||||
goto out2;
|
||||
}
|
||||
if (dvp->v_mount != vp->v_mount) {
|
||||
VOP_ABORTOP(dvp, cnp);
|
||||
error = EXDEV;
|
||||
goto out2;
|
||||
}
|
||||
if (vp != tdvp && (error = VOP_LOCK(tdvp))) {
|
||||
VOP_ABORTOP(vp, cnp);
|
||||
if (dvp != vp && (error = VOP_LOCK(vp))) {
|
||||
VOP_ABORTOP(dvp, cnp);
|
||||
goto out2;
|
||||
}
|
||||
ip = VTOI(tdvp);
|
||||
ip = VTOI(vp);
|
||||
if ((nlink_t)ip->i_nlink >= LINK_MAX) {
|
||||
VOP_ABORTOP(vp, cnp);
|
||||
VOP_ABORTOP(dvp, cnp);
|
||||
error = EMLINK;
|
||||
goto out1;
|
||||
}
|
||||
if (ip->i_flags & (IMMUTABLE | APPEND)) {
|
||||
VOP_ABORTOP(vp, cnp);
|
||||
VOP_ABORTOP(dvp, cnp);
|
||||
error = EPERM;
|
||||
goto out1;
|
||||
}
|
||||
ip->i_nlink++;
|
||||
ip->i_flag |= IN_CHANGE;
|
||||
tv = time;
|
||||
error = VOP_UPDATE(tdvp, &tv, &tv, 1);
|
||||
error = VOP_UPDATE(vp, &tv, &tv, 1);
|
||||
if (!error)
|
||||
error = ufs_direnter(ip, vp, cnp);
|
||||
error = ufs_direnter(ip, dvp, cnp);
|
||||
if (error) {
|
||||
ip->i_nlink--;
|
||||
ip->i_flag |= IN_CHANGE;
|
||||
}
|
||||
FREE(cnp->cn_pnbuf, M_NAMEI);
|
||||
out1:
|
||||
if (vp != tdvp)
|
||||
VOP_UNLOCK(tdvp);
|
||||
if (dvp != vp)
|
||||
VOP_UNLOCK(vp);
|
||||
out2:
|
||||
vput(vp);
|
||||
vput(dvp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue