Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
VOP_RENAME(9)		 BSD Kernel Developer's	Manual		 VOP_RENAME(9)

NAME
     VOP_RENAME	-- rename a file

SYNOPSIS
     #include <sys/param.h>
     #include <sys/vnode.h>

     int
     VOP_RENAME(struct vnode *fdvp, struct vnode *fvp,
	 struct	componentname *fcnp, struct vnode *tdvp, struct	vnode *tvp,
	 struct	componentname *tcnp);

DESCRIPTION
     This renames a file and possibly changes its parent directory.  If	the
     destination object	exists,	it will	be removed first.

     Its arguments are:

     fdvp  The vnode of	the old	parent directory.

     fvp   The vnode of	the file to be renamed.

     fcnp  Pathname information	about the file's current name.

     tdvp  The vnode of	the new	parent directory.

     tvp   The vnode of	the target file	(if it exists).

     tcnp  Pathname information	about the file's new name.

LOCKS
     The source	directory and file are unlocked	but are	expected to have their
     ref count bumped on entry.	 The VOP routine is expected to	vrele(9) both
     prior to returning.

     The destination directory and file	are locked as well as having their ref
     count bumped.  The	VOP routine is expected	to vput(9) both	prior to re-
     turning.

PSEUDOCODE
     int
     vop_rename(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp,
		struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp)
     {
	 int doingdirectory = 0;
	 int error = 0;

	 /*
	  * Check for cross-device rename.
	  */
	 if (fvp->v_mount != tdvp->v_mount) {
	     error = EXDEV;
	 abortit:
	     if	(tdvp == tvp)
		 vrele(tdvp);
	     else
		 vput(tdvp);
	     if	(tvp)
		 vput(tvp);
	     vrele(fdvp);
	     vrele(fvp);
	     return error;
	 }

	 if (tvp exists	and is immutable) {
	     error = EPERM;
	     goto abortit;
	 }

	 /*
	  * POSIX: "If the old argument	and the	new argument
	  * both refer to links	to the same existing file,
	  * the	rename() function shall	return successfully
	  * and	perform	no other action."
	  * The	upper layers already handle this case.
	  */
	 KASSERT(fvp !=	tvp, ("vop_rename: source and destination are the same"));

	 if (fvp is immutable) {
	     error = EPERM;
	     goto abortit;
	 }

	 error = VOP_LOCK(fvp);
	 if (error)
	     goto abortit;

	 if (vp	is a directory)	{
	     /*
	      *	Avoid ".", "..", and aliases of	"." for	obvious	reasons.
	      */
	     if	((fcnp->cn_namelen == 1	&& fcnp->cn_nameptr[0] == '.')
		 || fdvp == fvp
		 || ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT)) {
		 VOP_UNLOCK(fvp);
		 error = EINVAL;
		 goto abortit;
	     }
	     doingdirectory = 1;
	 }
	 vrele(fdvp);

	 /*
	  * Bump link count on fvp while we are	moving stuff around.  If we
	  * crash before completing the	work, the link count may be wrong
	  * but	correctable.
	  */
	 ...;

	 /*
	  * If ".." must be changed (ie	the directory gets a new
	  * parent) then the source directory must not be in the
	  * directory hierarchy	above the target, as this would
	  * orphan everything below the	source directory. Also
	  * the	user must have write permission	in the source so
	  * as to be able to change "..".
	  */
	 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred,	tcnp->cn_thread);
	 VOP_UNLOCK(fvp);
	 if (doingdirectory && fdvp != tdvp) {
	     /*
	      *	Check for pathname conflict.
	      */
	     ...;
	 }

	 /*
	  * If the target doesn't exist, link the target to the	source and
	  * unlink the source.	Otherwise, rewrite the target directory	to
	  * reference the source and remove the	original entry.
	  */
	 if (tvp == NULL) {
	     /*
	      *	Account	for ".." in new	directory.
	      */
	     if	(doingdirectory	&& fdvp	!= tdvp) {
		 /*
		  * Increase link count	of tdvp.
		  */
		 ...;
	     }

	     /*
	      *	Add name in new	directory.
	      */
	     ...;

	     if	(error)	{
		 if (doingdirectory && fdvp != tdvp) {
		     /*
		      *	Decrease link count if tdvp.
		      */
		     ...;
		 }
		 goto bad;
	     }
	     vput(tdvp);
	 } else	{
	     /*
	      *	Target must be empty if	a directory and	have no	links
	      *	to it. Also, ensure source and target are compatible
	      *	(both directories, or both not directories).
	      */
	     if	(tvp is	a directory) {
		 if (tvp is not	empty) {
		     error = ENOTEMPTY;
		     goto bad;
		 }
		 if (!doingdirectory) {
		     error = ENOTDIR;
		     goto bad;
		 }
		 /*
		  * Update name	cache since directory is going away.
		  */
		 cache_purge(tdvp);
	     } else if (doingdirectory)	{
		 error = ENOTDIR;
		 goto bad;
	     }

	     /*
	      *	Change name tcnp in tdvp to point at fvp.
	      */
	     ...;

	     /*
	      *	If the target directory	is in same directory as	the source
	      *	directory, decrement the link count on the parent of the
	      *	target directory.  This	accounts for the fact that a
	      *	directory links	back to	its parent with	"..".
	      */
	     if	(doingdirectory	&& fdvp	== tdvp) {
		 /*
		  * Decrement link count of tdvp.
		  */
		 ...;
	     }
	     vput(tdvp);

	     /*
	      *	Decrement the link count of tvp	since the directory no
	      *	longer points at it.
	      */
	     ...;
	     if	(doingdirectory) {
		 /*
		  * Clean up the old directory tvp.
		  */
		 ...;
	     }
	     vput(tvp);
	 }

	 /*
	  * Unlink the source.	If a directory was moved to a new parent,
	  * update its ".." entry.  Gobs of ugly UFS code omitted here.
	  */
	 ...;

     bad:
	 if (tvp)
	     vput(tvp);
	 vput(tdvp);
     out:
	 if (VOP_LOCK(fvp) == 0) {
	     /*
	      *	Decrement link count of	fvp.
	      */
	     ...;
	     vput(fvp);
	 } else
	     vrele(fvp);

	 return	error;
     }

ERRORS
     [EPERM]		The file is immutable.

     [EXDEV]		It is not possible to rename a file between different
			file systems.

     [EINVAL]		An attempt was made to rename .	or .., or to perform
			an operation which would break the directory tree
			structure.

     [ENOTDIR]		An attempt was made to rename a	directory to a file or
			vice versa.

     [ENOTEMPTY]	An attempt was made to remove a	directory which	is not
			empty.

SEE ALSO
     vnode(9)

AUTHORS
     This manual page was written by Doug Rabson.

BSD				 July 24, 1996				   BSD

NAME | SYNOPSIS | DESCRIPTION | LOCKS | PSEUDOCODE | ERRORS | SEE ALSO | AUTHORS

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=VOP_RENAME&sektion=9&manpath=FreeBSD+7.2-RELEASE>

home | help