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

📄 gfs_syscalls.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)gfs_syscalls.c	4.13	(ULTRIX)	5/2/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1986, 1987, 1988 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 * * 02 May 91 -- darrell *	Fixed a missing ")" in copen(); * * 01 May 91 -- sue *	Back out previous change which was to fix copen() to prevent *	disappearing tape drives.  On VAX, caused problems using *	file command on /dev/tty*. * * 10 Apr 91 -- prs *	The setjmp case of copen() cannot call closef(). Simply *	deallocate the file table entry. * * 28 Feb 91 -- prs *	Added support for a configurable number of open *	file descriptors. * * 27 Feb 91 -- chet *	Fix filesystem timestamping. * * 21 Jan 91 -- prs *	Added zeroing the f_data field to the error case in copen(). *	Also removed some obsolete vhangup() leftovers. * * 15 Oct 90 -- dws *	Fixed saccess() to handle 'noexec' filesystems correctly. * * 27 Sep 90 -- prs *	Prevented rename(from, ".") in rename(). * * 17 May 90 -- prs *	Fixed bug in copen() which left an unreferenced file descriptor *	in the uarea. * * 17 Jan 90 -- prs *	Added the restriction that a POSIX process cannot link to *	a directory. * * 12 Jan 90 -- prs *	Fixed saccess() to restore euid and egid before returning. * * 08 Dec 89 -- cb *	Fixed getmnt to exit syscall after a ^C. *  * 08 Dec 89 -- prs *	Checked u.u_error after a call to GUPDATE in link(). *	If the gupdate failed, don't bother doing the namei *	on the target. * * 14 Nov 89 -- prs *	Added POSIX check to prevent unlinking of TEXT gnodes. * * 25 Jul 89 -- chet *	New sync() system call * * 08 Jun 89 -- lebel * 	Fixed BLKANDSET code in copen - open always returned fd of 0 * 	for character special files * * 04 Apr 89 -- prs *	Added SMP quota locking. * * 16 Feb 89 -- prs *      Added XOPEN check to prevent unlinking of TEXT gnodes. * * 08 Dec 88 -- prs *      Added POSIX mode access time setting *      in getdirentries(). * * 09 Jan 89 -- condylis *	Modified sync and getmnt to run on any processor. * * 11 Oct 88 -- prs *	Changed rmdir() to pass the sfs a directory gp, and properly *	fixed the GNOFUNC error leg. * * 14 Sep 88 -- chet *	Fix another bug in link() due to GUPDATE calls on a readonly *	remote filesystem. * * 22 Aug 88 -- prs *	Changed copen() to only allow root to create a file with the *	sticky bit set. * * 04 Aug 88 -- chet *      Fix problems in link() due to GUPDATE calls that destroy u.u_error. * * 28 Jul 88 -- prs *	SMP - All system calls except sync() and rename() are safe. * * 23 Feb 88 -- map *	Fix problem in chown(). In some cases it would fail but not return *	an errno. * * 10 Feb 88 -- map *	Rewrite utimes() to allow POSIX and SVID utime() behavior. The utime() *	library routine calls utimes(). A NULL time parameter will now default *	to the current time as specified in the utime() function. If the time *	parameter is NULL EITHER the owner(or su) OR a process with write *	access can update the time.  This is not a security hole as a user *	with write access can update the time through other means prior to *	this change. *  * 10 Feb 88 -- prs *	Modified to handle new fifo code. * * 08 Feb 88 -- prs *	Fixed lseek to return an error if the target offset is negative *	for a regular file. * * 26 Jan 88 -- chet *	Removed access check in gfs_getdirentries(). This *	check has been moved down to the specific filesystems. * * 08 Jan 88 -- prs *	Removed lseek change that checked for a negative offset. * * 04 Jan 88 -- prs *	Added a check to link() that verified link count of gnode *	did not exceed LINK_MAX. * * 12 Dec 87 -- prs *	Fixed lseek to return an error if the target offset is negative. * * 12-11-87	Robin L. and Larry C. *	Added new kmalloc memory allocation to system. * * 17 Nov 87 -- map *	Allow user to chown the group id of a file to another group *	to which they belong. Allows chgrp to not be suid. POSIX requirement. * * 15 Sep 87 -- prs *	Changed copen to validate the fp after GOPEN call. * * 09 Sep 87 -- map *	saccess() changed to check for invalid mode. POSIX requirement * * 19 Aug 87 -- cb *      getmnt() returned to original state.  readlink changed to return *      EINVAL if file is not a symbolic link. * * 13 Aug 87 -- cb *	Fixed getmnt so it will parse a block device path correctly * * 14 Jul 87 -- cb *	Changed mknod interface: added a dev_t. * * 11 Jun 87 -- prs *	Free cred if call to GOPEN fails in copen routine. * * 12 May 87 -- chet *	Added new getmnt() interface code. * * 03 Mar 87 -- chet *	Unlocked gnode before doing GSTAT so that locks won't *	propagate up file tree when a slow operation takes place. * * 13 Feb 87 -- prs *	Removed check for m_dev to be null in sync. The check prevented *	sync on a device with major number 0. * * 15 January 86 -- Chase *	added code to check for failure on truncate in copen() * * 11 Sept 86 -- koehler *	changes for new namei interface * * 12 Sept 86 -- koehler *	symlink errno change * * 2  Oct 86 -- Larry Cohen *	refix shared line bug in copen ***********************************************************************/#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 "../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/kmalloc.h"#include "../h/exec.h"#include "../h/limits.h"extern	struct gnode *fref();link() {        register struct gnode *source_gp, *target_pgp;        register struct a {                char    *source;                char    *target;        } *uap = (struct a *)u.u_ap;        register struct nameidata *ndp = &u.u_nd;        int     error = 0;        ndp->ni_nameiop = LOOKUP | FOLLOW;        KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);        if (ndp->ni_dirp == NULL) {                u.u_error = EIO;                return;        }        if (u.u_error = copyinstr(uap->source, ndp->ni_dirp, MAXPATHLEN,				  (u_int *) 0))                goto free;        source_gp = gfs_namei(ndp);        if (source_gp == NULL)                goto free;        if (source_gp->g_nlink >= LINK_MAX) {                gput(source_gp);                u.u_error = EMLINK;                goto free;        }        if (((source_gp->g_mode & GFMT) == GFDIR) && 	     (!suser() || (u.u_procp->p_progenv == A_POSIX))) {                gput(source_gp);		u.u_error = EPERM;                goto free;        }        if (u.u_error = copyinstr(uap->target, ndp->ni_dirp, MAXPATHLEN,				  (u_int *) 0)) {                gput(source_gp);                goto free;        }        /* this stuff is done here to avoid races in the fs */        source_gp->g_nlink++;	/*	 * A lot of games are played here	 * with error and u.u_error because of the GUPDATE calls	 * that don't do anything useful except for UFS, and are guaranteed	 * to clobber u.u_error for NFS.	 * There is a subtle UFS case as well, where an I/O error	 * on the inode update clobbers an already failing syscall's	 * u.u_error with EIO.	 *	 * I finally decided to bite the bullet and put ISLOCAL	 * checks around the GUPDATE calls - 9/8/88 - chet	 */	if (ISLOCAL(source_gp->g_mp)) {		source_gp->g_flag |= GCHG;		(void) GUPDATE(source_gp, timepick, timepick, 1, u.u_cred);		if (u.u_error) {			error = u.u_error;			gfs_unlock(source_gp);			goto errout;		}	}        gfs_unlock(source_gp);        ndp->ni_nameiop = CREATE;        target_pgp = gfs_namei(ndp);        if (u.u_error) {                error = u.u_error;      /* save the error code */                goto errout;        }        if (target_pgp != NULL) {                gput(target_pgp);                error = EEXIST;         /* save the error code */                goto errout;        }        target_pgp = ndp->ni_pdir;        if (target_pgp->g_mp != source_gp->g_mp) {                gput(target_pgp);                error = EXDEV;          /* save the error code */                goto errout;        }        /*         * LINK should take three arguments, gp of source, gp of parent         * of source, and source component.         */        /* The fs specific routine does all de-referencing */        if (GLINK(source_gp, ndp) == GNOFUNC) {                u.u_error = EOPNOTSUPP;                gput(target_pgp);                grele(source_gp);        }        goto free;errout:        gfs_lock(source_gp);        source_gp->g_nlink--;	if (ISLOCAL(source_gp->g_mp)) {		source_gp->g_flag |= GCHG;		(void) GUPDATE(source_gp, timepick, timepick, 1, u.u_cred);	}        gput(source_gp);        u.u_error = error; /* restore the error code after GUPDATE*/free:        KM_FREE(ndp->ni_dirp, KM_NAMEI);}unlink(){	register struct a {		char	*fname;	} *uap = (struct a *)u.u_ap;	register struct gnode *gp, *dp;	register struct nameidata *ndp = &u.u_nd;	register int ret;		ndp->ni_nameiop = DELETE | LOCKPARENT;	KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->fname, ndp->ni_dirp, MAXPATHLEN,				  (u_int *) 0)) {	         goto out2;	}	gp = gfs_namei(ndp);	if (gp == NULL) {	         goto out2;	}		dp = (struct gnode *)ndp->ni_pdir;	/* only non POSIX root can unlink a directory */	if ((gp->g_mode&GFMT) == GFDIR) {		if ((u.u_procp->p_progenv == A_POSIX) ||		     !suser()) {			if (u.u_error == 0)				u.u_error = EPERM;			goto out;		}	}	/*	 * Don't unlink a mounted file.	 */	if (gp->g_dev != dp->g_dev) {		u.u_error = EBUSY;		goto out;	}	if (gp->g_flag&GTEXT) {		xrele(gp);	/* try once to free text */	}	/*         * SysV and POSIX cannot remove the last link to a shared text file.         */        if ((u.u_procp->p_progenv & (A_POSIX|A_SYSV)) &&            (gp->g_flag&GTEXT) && (gp->g_nlink == 1)) {                u.u_error = ETXTBSY;                goto out;        }	if (GUNLINK(gp, ndp) == GNOFUNC)		u.u_error = EOPNOTSUPP;out:	if (dp == gp) {		grele(gp);		gput(gp);	} else {		gput(dp);		gput(gp);	}out2:        KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Mkdir system call */mkdir(){	register struct a {		char	*name;		int	dmode;	} *uap = (struct a *) u.u_ap;	register struct gnode *gp;	register struct nameidata *ndp = &u.u_nd;	uap = (struct a *)u.u_ap;	ndp->ni_nameiop = CREATE;	KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->name, ndp->ni_dirp, MAXPATHLEN,				  (u_int *)0)) {	        goto out;	}		gp = gfs_namei(ndp);	if (u.u_error) {	        goto out;	}	if (gp != NULL) {		u.u_error = EEXIST;		gput(gp);	        goto out;	}	if ((gp = GMKDIR(ndp->ni_pdir, ndp->ni_dirp, uap->dmode)) == 	    (struct gnode *) GNOFUNC)		u.u_error = EOPNOTSUPP;	else		if (!u.u_error)			grele(gp);out:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Rmdir system call. */rmdir(){	register struct a {		char	*name;	} *uap = (struct a *)u.u_ap;	register struct gnode *gp;	register struct nameidata *ndp = &u.u_nd;	ndp->ni_nameiop = DELETE | LOCKPARENT;	KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->name, ndp->ni_dirp, MAXPATHLEN,				  (u_int *)0)) {	        goto out;	}	gp = gfs_namei(ndp);	if (gp == NULL) {	        goto out;	}		/*	 * GFS assures the sfs gp is a directory.	 */	if ((gp->g_mode & GFMT) != GFDIR) {		u.u_error = ENOTDIR;		goto bad;	}		if (GRMDIR(gp, ndp) == GNOFUNC) {		u.u_error = EOPNOTSUPP;		goto bad;	}	goto out;bad:	if (ndp->ni_pdir == gp)		grele(ndp->ni_pdir);	else		gput(ndp->ni_pdir);	gput(gp);out:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * mode mask for creation of files */umask(){	register struct a {		int	mask;	} *uap = (struct a *)u.u_ap;	u.u_r.r_val1 = u.u_cmask;	u.u_cmask = uap->mask & 07777;}struct gnode *maknode(mode, ndp)	register int mode;	register struct nameidata *ndp;{	if (GMAKNODE(mode, (dev_t) 0, ndp) == (struct gnode *) GNOFUNC)		u.u_error = EOPNOTSUPP;}/* * Rename system call. * 	rename("foo", "bar"); * is essentially *	unlink("bar"); *	link("foo", "bar"); *	unlink("foo"); * but ``atomically''.  Can't do full commit without saving state in the * inode on disk which isn't feasible at this time.  Best we can do is * always guarantee the target exists. * * Basic algorithm is: * * 1) Bump link count on source while we're linking it to the *    target.  This also insure the gnode won't be deleted out *    from underneath us while we work (it may be truncated by *    a concurrent `trunc' or `open' for creation). * 2) Link source to destination.  If destination already exists, *    delete it first. * 3) Unlink source reference to gnode if still around. *    If a directory was moved and the parent of the destination *    is different from the source, patch the ".." entry in the *    directory. * * Source and destination must either both be directories, or both * not be directories.  If target is a directory, it must be empty. */rename(){	register struct a {		char	*from;		char	*to;	} *uap;	register struct gnode *source_gp;	register struct nameidata *source_ndp = &u.u_nd;	struct nameidata target_ndp;		/* get us a pointer to the from name */		uap = (struct a *)u.u_ap;	source_ndp->ni_nameiop = DELETE | LOCKPARENT;	KM_ALLOC(source_ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (source_ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->from, source_ndp->ni_dirp, MAXPATHLEN,				  (u_int *) 0)) {	        goto out1;	}	KM_ALLOC(target_ndp.ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (target_ndp.ni_dirp == NULL) {		u.u_error = EIO;	        goto out1;	}	 	if (u.u_error = copyinstr(uap->to, target_ndp.ni_dirp, MAXPATHLEN,				  (u_int *) 0)) {	        goto out2;	}	/*	 * Prevent rename(from, ".")	 */	if (!strcmp(target_ndp.ni_dirp, ".")) {		u.u_error = EINVAL;		goto out2;	}		source_gp = gfs_namei(source_ndp);		if (source_gp == NULL || u.u_error) {	        goto out2;	}		/* XXX */	/* this is UFS specific */	if (ISLOCAL(source_gp->g_mp)) {		if (u.u_error = copyinstr(uap->from, source_ndp->ni_dirp, 					  MAXPATHLEN, (u_int *) 0)) {	        goto out2;		}	}	target_ndp.ni_nameiop = CREATE | LOCKPARENT | NOCACHE;		if (GRENAMEG(source_gp, u.u_cdir, source_ndp, u.u_cdir, &target_ndp,		     0)	== GNOFUNC) {		u.u_error = EOPNOTSUPP;		gput(source_gp);		gput(source_ndp->ni_pdir);	}out2:	KM_FREE(target_ndp.ni_dirp, KM_NAMEI);out1:	KM_FREE(source_ndp->ni_dirp, KM_NAMEI);}extern	struct fileops gnodeops;extern	int	soo_rw(), soo_ioctl(), soo_select(), gno_close();struct	fileops	portops =    { soo_rw, soo_ioctl, soo_select, gno_close };struct	file *getgnode();

⌨️ 快捷键说明

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