⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ufs_syscalls.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)ufs_syscalls.c	4.5	(ULTRIX)	5/3/91";#endif/************************************************************************ *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* *		Modification History * * 03 May 91 -- prs *	Prevent renaming directories over the source starting directory in *	ufs_rename(). * * 27 Feb 91 -- chet *	Fix filesystem timestamping. * * 18 Feb 91 -- prs *	Added SAVE_DIRP to the target namei op in ufs_rename(). Since *	the target name is translated several times and following *	symbolic links can trash the name, the name must be preserved. * * 27 Sep 90 -- prs *	Prevented rename(from, ".") in ufs_rename(). * * 07 Mar 90 -- prs *	Removed hack of unlocking target directory gnode before *	calling GNAMEI() if smp_owner check returned true. NFS *	server code will not call ufs_rename() with targer dir *	gnode locked. * * 17 Jan 90 -- prs *	Verified directories being referenced by ufs_rename() *	are not mount points. * * 14 Nov 89 -- prs *      Decremented link count of parent directory when a *      rename(fromdir, todir) within the same directory, and *      todir exists. Also added ETXTBSY detection if in POSIX *      mode to ufs_rename(). * * 04 Nov 88 -- prs *	Added sticky bit check to ufs_rename() that enforces *	sticky bit directory rules to target files. * * 11 Oct 88 -- prs *	Removed a check from ufs_rmdir() that is now done at the *	GFS layer. The check being to pass the sfs a directory *	gnode. * *  1 Sep 88 -- chet *	Set XBAD text flag if unlinking an executing text file *	so that resources are freed * * 23 Aug 88 -- condylis *	Added 2.4 update to ufs_link.  GUPDATE source gnode after *	decrementing link count. * * 15 Aug 88 -- prs *	Nulled g_fifo before returning from ufs_maknode(). * * 28 Jul 88 -- prs *	SMP - System call turn on. * * 24 Jun 88 -- prs *	Fixed error returns for EISDIR and ENOTDIR from ufs_rename(). * * 14 Jan 88 -- chet *	Removed gennum++'s from ufs_unlink() and ufs_rmdir(). *	The increment is now in ufs_grele(). * * 04 Jan 88 -- prs *	Added a check to ufs_mkdir that verified the link count in *	the parents directory gnode did not exceed LINK_MAX. * * 14 Jul 87 -- cb *	Changed mknod interface. * * 11 Sep 86 -- koehler *	fixed a link bug -- changed the namei interface * * 11 Nov 85 -- depp *	Removed all conditional compiles for System V IPC. * * 	Stephen Reilly, 09-Sep-85 *	Modified to handle the new 4.3BSD namei code. * *	Stephen Reilly, 07-Aug-85 * 003- Fixed a stale inode cache problem that was occuring with the *	rmdir syscall. * *	Larry Cohen, 13-April-85 *		If open BLKINUSE and openi returns EALREADY then wait *		wait for line to unblock again. *		Also call f_ops ioctl if open FBLKANDSET * * 	Larry Cohen, 4-April-85 * 002- Changes to support open block if in use capability. * *									* * 15 Mar 85 -- funding							* *	Added named pipe support (re. System V named pipes)		* * * 26 Oct 84 -- jrs *	Add support for namei cacheing.  Major changes to rename() * *	Stephen Reilly, 11-Jul-84 * 001- There is a race condition between unlink and rename syscalls *	that can cause a panic with the message "freeing free inode *	panic". This fix came from Kirk Mckusick. */#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/kernel.h"#include "../h/file.h"#include "../h/stat.h"#include "../h/gnode.h"#include "../ufs/fs.h"#include "../h/buf.h"#include "../h/proc.h"#include "../h/quota.h"#include "../h/uio.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/mount.h"#include "../h/ioctl.h"#include "../h/limits.h"#include "../h/text.h"#include "../h/exec.h"#ifdef GFSDEBUGextern short GFS[];#endifextern struct gnode *ufs_galloc();/* * link system call * gp is the gnode to be linked to, ndp is the nameidata point used * to get gp and which may be trashed. linkname is the new linkname. */ufs_link(source_gp, target_ndp)	register struct	gnode *source_gp;	register struct nameidata *target_ndp;{        gassert(source_gp);	u.u_error = direnter(source_gp, target_ndp);	if (u.u_error) {		ufs_glock(source_gp);		source_gp->g_nlink--;		source_gp->g_flag |= GCHG;		(void) GUPDATE(source_gp, timepick, timepick, 1, u.u_cred);		ufs_gunlock(source_gp);	}	grele(source_gp);}/* * Unlink system call. * Hard to avoid races here, especially * in unlinking directories. */ufs_unlink(gp, ndp)	register struct gnode *gp;	register struct nameidata *ndp;{        gassert(gp);	if (dirremove(ndp)) {		gp->g_nlink--;		gp->g_flag |= GCHG;		/*		 * If unlinking last link to an executing text file,		 * mark it so that file system resources are freed		 * as soon as last executing process exits (else the		 * text table will hold a ref. on the gnode, keeping		 * the resources held).		 */		if (gp->g_nlink <= 0 && gp->g_flag & GTEXT)			gp->g_textp->x_flag |= XBAD;		}#ifdef GFSDEBUG	if(GFS[10])		cprintf("ufs_unlink: gp 0x%x (%d) nlink %d u.u_error %d\n",		gp, gp->g_number, gp->g_nlink, u.u_error);#endif}/* * XXX Chase -- ugly temporary hack to fix rename failures. * ssd and tsd are the starting directories for namei's on source * and target respectively.  These are not needed for the local case * because both source and target pathnames are relative to the (same) * current directory.  Arguments to NFS rename operation are dirs and * single-component pathnames, so the source and target "pathnames" * may not be relative to the same directory.  Since there may be up * to four calls to namei for a single rename operation, u.u_cdir * has to change in the middle of ufs_rename in order to properly * handle an NFS rename operation with the old interface. * * Let's find a more elegant solution to this problem someday. * * A side effect of namei is following symbolic links will trash ni_dirp. * When ni_dirp must be preserved, the SAVE_DIRP flag must be set in * ni_nameiop. ufs_rename() assumes the source_ndp->ni_dirp is correct. * ufs_rename() must protect target_ndp->ni_dirp. */ufs_rename(gp, ssd, source_ndp, tsd, target_ndp, flag)	register struct gnode *gp;	struct gnode *ssd, *tsd;	register struct nameidata *source_ndp;	register struct nameidata *target_ndp;	int flag;{	register struct gnode *dp;	register struct gnode *target_gp;	struct dirtemplate dirbuf;	register int doingdirectory = 0;	int oldparent = 0, newparent = 0;	int error = 0;	int write_access_err = 0;	target_ndp->ni_nameiop |= SAVE_DIRP;	dp = source_ndp->ni_pdir;	/*	 * Don't allow rename(from, ".")	 */	if (!strcmp(target_ndp->ni_dirp, ".")) {		gput(dp);		if (dp == gp)			grele(gp);		else			gput(gp);		u.u_error = EINVAL;		return;	}	/* 	 *lock the parent because we may make changes if there is a 	 * directory move	 */		if ((gp->g_mode&GFMT) == GFDIR) {		register struct direct *d;		d = &source_ndp->ni_dent;#ifdef GFSDEBUG		if(GFS[16])			cprintf("ufs_rename: source gp 0x%x (%d) '%s' is dir\n",			gp, gp->g_number, d->d_name);#endif		/*		 * Avoid ".", "..", and aliases of "." for obvious reasons.		 */		if ((d->d_namlen == 1 && d->d_name[0] == '.') ||		    (d->d_namlen == 2 && bcmp(d->d_name, "..", 2) == 0) ||		    (dp == gp) || (gp->g_flag & GRENAME)) {			gput(dp);			if (dp == gp)				grele(gp);			else				gput(gp);			u.u_error = EINVAL;			return;		}		/*		 * Source can't be a mount point.		 */		if (gp->g_dev != dp->g_dev) {			gput(dp);			if (dp == gp)				grele(gp);			else				gput(gp);			u.u_error = EBUSY;			return;		}		gp->g_flag |= GRENAME;		oldparent = dp->g_number;		doingdirectory++;	}	gput(dp);	/*	 * 1) Bump link count while we're moving stuff	 *    around.  If we crash somewhere before	 *    completing our work, the link count	 *    may be wrong, but correctable.	 */	gp->g_nlink++;	gp->g_flag |= GCHG;#ifdef GFSDEBUG	if(GFS[16])		cprintf("ufs_rename: updating target\n");#endif	ufs_gupdat(gp, timepick, timepick, 1, (struct ucred *) 0);	/*	 * We would like to do the access check further down (perms	 * may change), but we need to have the gnode locked and it	 * won't be safe to lock it again. We could do the access	 * check even further down (when we actually write gp, then	 * called "target_gp"), but if it failed we'd be too far into	 * the rename operation to back out reasonably. This hack	 * should do the job.	 */	if (access(gp, GWRITE)) {	        write_access_err = u.u_error;		u.u_error = 0;	}	gfs_unlock(gp);	/* this should really be done in gfs */	u.u_cdir = tsd;	target_gp = GNAMEI(target_ndp);	if(u.u_error) {#ifdef GFSDEBUG		if(GFS[16])			cprintf("ufs_rename: target '%s' error %d\n",			target_ndp->ni_dirp, u.u_error);#endif		gfs_lock(gp);		gp->g_nlink--;		gp->g_flag |= GCHG;		gput(gp);		return;	}	dp = target_ndp->ni_pdir;		/*	 * 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 "..". We must repeat the call 	 * to namei, as the parent directory is unlocked by the	 * call to checkpath().	 */	if (oldparent != dp->g_number)		newparent = dp->g_number;	if (doingdirectory && newparent) {	        if (write_access_err) {		        u.u_error = write_access_err;			goto bad;		}		do {			dp = target_ndp->ni_pdir;			if (target_gp != NULL)				gput(target_gp);			u.u_error = checkpath(gp, dp, flag);			if (u.u_error)				goto out;			u.u_cdir = tsd;			target_gp = GNAMEI(target_ndp);			if (u.u_error) {				error = u.u_error;				goto out;			}		} while (dp != target_ndp->ni_pdir);	}	/*	 * 2) If target doesn't exist, link the target	 *    to the source and unlink the source. 	 *    Otherwise, rewrite the target directory	 *    entry to reference the source gnode and	 *    expunge the original entry's existence.	 */	if (target_gp == NULL) {#ifdef GFSDEBUG		if(GFS[16])			cprintf("ufs_rename: target doesn't exist\n");#endif		if (dp->g_dev != gp->g_dev) {			error = EXDEV;			goto bad;		}		/*		 * Account for ".." in new directory.		 * When source and destination have the same		 * parent we don't fool with the link count.		 */		if (doingdirectory && newparent) {			gassert(dp);	/* PRS - Temporary */			dp->g_nlink++;			dp->g_flag |= GCHG;			ufs_gupdat(dp, timepick, timepick, 1,				   (struct ucred *) 0);		}#ifdef GFSDEBUG		if(GFS[16])			cprintf("ufs_rename: doing direnter on gp 0x%x (%d) '%s'\n",			gp, gp->g_number, target_ndp->ni_dirp);#endif		error = direnter(gp, target_ndp);		if (error)			goto out;	} else {		/*		 * If the parent of the target and the target		 * are not on the same device, target is a mount		 * point.		 */		if (target_gp->g_dev != dp->g_dev) {			error = EBUSY;			goto bad;		}		/*		 * Can't rename across file systems.		 */		if (target_gp->g_dev != gp->g_dev) {			error = EXDEV;			goto bad;		}		/*		 * Short circuit rename(foo, foo).		 */		if (target_gp->g_number == gp->g_number)			goto bad;		/*                 * If the parent directory is "sticky", then the user must                 * own the parent directory, or the destination of the rename,                 * otherwise the destination may not be changed (except by                 * root). This implements append-only directories.                 */                if ((dp->g_mode & GSVTX) && u.u_uid != 0 &&                    u.u_uid != dp->g_uid && target_gp->g_uid != u.u_uid) {                        error = EPERM;                        goto bad;                }		/*                 * If POSIX, cannot remove target if busy shared executable.                 */               if ((u.u_procp->p_progenv == A_POSIX) &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -