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

📄 ufs_syscalls.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
		   (target_gp->g_flag&GTEXT)) {			xrele(target_gp);			if (target_gp->g_flag&GTEXT) {				error = ETXTBSY;				goto bad;			}		}		/*		 * Target must be empty if a directory		 * and have no links to it.		 * Also, insure source and target are		 * compatible (both directories, or both		 * not directories).		 */		if ((target_gp->g_mode&GFMT) == GFDIR) {			if (!dirempty(target_gp, dp->g_number) || target_gp->g_nlink > 2) {				error = ENOTEMPTY;				goto bad;			}			if (!doingdirectory) {				error = EISDIR;				goto bad;			}			cacheinval(dp);		} else if (doingdirectory) {			error = ENOTDIR;			goto bad;		}		/*		 * If we are renaming directories and we will be		 * rewriting the source starting directory, fail		 * the operation because we will need the source		 * starting directory in tact to remove the source_gp.		 */		if (doingdirectory && target_gp == ssd) {			u.u_error = EINVAL;			goto bad;		}		dirrewrite(dp, gp, target_ndp);		if (u.u_error) {			error = u.u_error;			goto bad1;		}		/*		 * Adjust the link count of the target to		 * reflect the dirrewrite above.  If this is		 * a directory it is empty and there are		 * no links to it, so we can squash the gnode and		 * any space associated with it.  We disallowed		 * renaming over top of a directory with links to		 * it above, as the remaining link would point to		 * a directory without "." or ".." entries.		 */		target_gp->g_nlink--;		if (doingdirectory) {			if (--target_gp->g_nlink != 0)				panic("rename: linked directory");			ufs_gtrunc(target_gp, (u_long)0, (struct ucred *) 0);			/*			 * We must decrement the link count of the			 * parent directory here, if we are unlinking			 * the target within the same directory as the			 * source.			 */			if (!newparent) {			        dp->g_nlink--;				dp->g_flag |= GCHG;			}		}		target_gp->g_flag |= GCHG;		gput(target_gp);		target_gp = NULL;	}	/*	 * 3) Unlink the source.	 */	source_ndp->ni_nameiop = DELETE | LOCKPARENT;		u.u_cdir = ssd;	target_gp = GNAMEI(source_ndp);	if (target_gp != NULL) {		dp = source_ndp->ni_pdir;	} else {		dp = NULL;	}	/*	 * Insure that the directory entry still exists and has not	 * changed while the new name has been entered. If the source is	 * a file then the entry may have been unlinked or renamed. In	 * either case there is no further work to be done. If the source	 * is a directory then it cannot have been rmdir'ed; its link	 * count of three would cause a rmdir to fail with ENOTEMPTY.	 * The GRENAME flag insures that it cannot be moved by another	 * rename.	 */	if (target_gp != gp) {		if (doingdirectory)			panic("rename: lost dir entry");	} else {		/*		 * If the source is a directory with a		 * new parent, the link count of the old		 * parent directory must be decremented		 * and ".." set to point to the new parent.		 */		if (doingdirectory && newparent) {			dp->g_nlink--;			dp->g_flag |= GCHG;			error = rdwri(UIO_READ, target_gp, (caddr_t)&dirbuf,				sizeof (struct dirtemplate), (off_t)0, 1,				(int *)0);			if (error == 0) {				if (dirbuf.dotdot_namlen != 2 ||					dirbuf.dotdot_name[0] != '.' ||					dirbuf.dotdot_name[1] != '.') {					printf("rename: mangled dir\n");				} else {					dirbuf.dotdot_ino = newparent;					(void) rdwri(UIO_WRITE, target_gp,					    (caddr_t)&dirbuf,					    sizeof (struct dirtemplate),					    (off_t)0, 1, (int *)0);					cacheinval(dp);				}			}		}		if (dirremove(source_ndp)) {			target_gp->g_nlink--;			target_gp->g_flag |= GCHG;		}		target_gp->g_flag &= ~GRENAME;		if (error == 0)		/* conservative */			error = u.u_error;	}	if (dp)		gput(dp);	if (target_gp)		gput(target_gp);	grele(gp);	if (error)		u.u_error = error;	return;bad:	gput(dp);bad1:	if (target_gp)		gput(target_gp);out:	gfs_lock(gp);	gp->g_nlink--;	gp->g_flag |= GCHG;	gput(gp);	if (error)		u.u_error = error;}/* * Make a new file. */extern struct gnode_ops *ufs_gnode_ops;struct gnode *ufs_maknode(mode, dev, ndp)	register int mode;        register dev_t dev;	register struct nameidata *ndp;{	register struct gnode *gp;	register struct gnode *pdir = ndp->ni_pdir;	register gno_t gpref;	int type;#ifdef GFSDEBUG	if(GFS[17])		cprintf("ufs_maknod: ndp 0x%x, ni_pdir 0x%x\n", ndp,		ndp->ni_pdir);#endif	if ((mode & GFMT) == GFDIR)		gpref = dirpref(FS(pdir));	else		gpref = pdir->g_number;	gp = ufs_galloc(pdir, gpref, mode);	if (gp == NULL) {		gput(pdir);		return (NULL);	}#ifdef QUOTA	if (gp->g_dquot != NODQUOT)		panic("maknode: dquot");#endif	gp->g_flag |= GACC|GUPD|GCHG;	gp->g_mode = mode & ~u.u_cmask;	gp->g_nlink = 1;	gp->g_uid = u.u_uid;	gp->g_gid = pdir->g_gid;	gp->g_rdev = dev;	gp->g_ops = ufs_gnode_ops;	type = gp->g_mode & GFMT;	if ((type == GFCHR) || (type == GFBLK) || (type == GFPORT)) {	        specvp(gp);        }	if (gp->g_mode & GSGID && !groupmember(gp->g_gid))		gp->g_mode &= ~GSGID;#ifdef QUOTA	gp->g_dquot = inoquota(gp);#endif	/*	 * Make sure gnode goes to disk before directory entry.	 */	ufs_gupdat(gp, timepick, timepick, 1, (struct ucred *) 0);	u.u_error = direnter(gp, ndp);	if (u.u_error) {		/*		 * Write error occurred trying to update directory		 * so must deallocate the gnode.		 */		gp->g_nlink = 0;		gp->g_flag |= GCHG;		gput(gp);		return (NULL);	}	if ((gp->g_mode & GFMT) == GFPORT)		gp->g_fifo = 0;	return (gp);}/* * A virgin directory (no blushing please). */struct dirtemplate mastertemplate = {	0, 12, 1, ".",	0, DIRBLKSIZ - 12, 2, ".."};struct gnode *ufs_mkdir(dp, name, mode)	register struct gnode *dp;	register int mode;	register char *name;{        register struct nameidata *ndp = &u.u_nd;        register struct gnode *gp;	struct dirtemplate dirtemplate;	if (dp->g_nlink >= LINK_MAX) {		gput(dp);		u.u_error = EMLINK;		return(NULL);	}	mode &= 0777;	mode |= GFDIR;	/*	 * Must simulate part of maknode here	 * in order to acquire the gnode, but	 * not have it entered in the parent	 * directory.  The entry is made later	 * after writing "." and ".." entries out.	 */	gp = ufs_galloc(dp, dirpref(FS(dp)), mode);	if (gp == NULL) {		gput(dp);		return(NULL);	}#ifdef QUOTA	if (gp->g_dquot != NODQUOT)		panic("mkdir: dquot");#endif	gp->g_flag |= GACC|GUPD|GCHG;	gp->g_mode = mode & ~u.u_cmask;	gp->g_nlink = 2;	gp->g_uid = u.u_uid;	gp->g_gid = dp->g_gid;	gp->g_ops = ufs_gnode_ops;#ifdef QUOTA	gp->g_dquot = inoquota(gp);#endif	ufs_gupdat(gp, timepick, timepick, 1, (struct ucred *) 0);	/*	 * Bump link count in parent directory	 * to reflect work done below.  Should	 * be done before reference is created	 * so reparation is possible if we crash.	 */	gassert(dp);	dp->g_nlink++;	dp->g_flag |= GCHG;	ufs_gupdat(dp, timepick, timepick, 1, (struct ucred *) 0);	/*	 * Initialize directory with "."	 * and ".." from static template.	 */	dirtemplate = mastertemplate;	dirtemplate.dot_ino = gp->g_number;	dirtemplate.dotdot_ino = dp->g_number;	u.u_error = rdwri(UIO_WRITE, gp, (caddr_t)&dirtemplate,		sizeof (dirtemplate), (off_t)0, 1, (int *)0);	if (u.u_error) {		dp->g_nlink--;		dp->g_flag |= GCHG;		gp->g_nlink = 0;		gp->g_flag |= GCHG;		gput(dp);		gput(gp);		/*		 * No need to do an explicit itrunc here,		 * grele will do this for us because we set		 * the link count to 0.		 */		return(NULL);	}		if (DIRBLKSIZ > FS(gp)->fs_fsize)		panic("mkdir: blksize");     /* XXX - should grow with bmap() */	else		gp->g_size = DIRBLKSIZ;	/*	 * Ref the parent directory , in case	 * we have to decrement link count	 * because direnter failure.	 */	gref(dp);	/*	 * Directory all set up, now	 * install the entry for it in	 * the parent directory.	 */	u.u_error = direnter(gp, ndp);	if (u.u_error) {		/*		 * Remove link from parent dir.		 * We refed the directory, to		 * ensure it would not go away.		 */		gfs_lock(dp);		dp->g_nlink--;		dp->g_flag |= GCHG;		gput(dp);#ifdef notdef		/*		 * A comedy of errors......		 * The following uncompiled code is completely		 * bogus. Since we were not rewriting, the		 * entry cannot exist in the cache.		 * Why bother doing a namei ? Besides, this code		 * does nothing about the parent dir, it decrements		 * the targer dir link count. - prs		 */		ndp->ni_nameiop = LOOKUP | NOCACHE;		ndp->ni_dirp = name;		/*		 * XXX - GNAMEI insists u.u_error be zero.		 * If not, it returnes root dp. Ouch !		 */		dp = GNAMEI(ndp);		if (dp) {			dp->g_nlink--;			dp->g_flag |= GCHG;			gput(dp);		}#endif		/*		 * Destroy target directory (that		 * was not entered in parent)		 */		gp->g_nlink = 0;		gp->g_flag |= GCHG;		gput(gp);		return(NULL);	}	grele(dp);	ufs_gunlock(gp);	return(gp);}ufs_rmdir(gp, ndp)	register struct gnode *gp;	register struct nameidata *ndp;{        register struct gnode *dp;	dp = ndp->ni_pdir;	gassert(dp);	/*	 * No rmdir "." please.	 */	if (dp == gp) {		grele(dp);		gput(gp);		u.u_error = EINVAL;		return;	}	/*	 * Don't remove a mounted on directory.	 */	if (gp->g_dev != dp->g_dev) {		u.u_error = EBUSY;		goto out;	}	/*	 * Verify the directory is empty (and valid).	 * (Rmdir ".." won't be valid since	 *  ".." will contain a reference to	 *  the current directory and thus be	 *  non-empty.)	 */#ifdef GFSDEBUG	if(GFS[13])		cprintf("ufs_rmdir: gp 0x%x (%d) links %d size %d\n", gp, gp->g_number,		gp->g_nlink, gp->g_size);#endif	if (gp->g_nlink != 2 || !dirempty(gp, dp->g_number)) {		u.u_error = ENOTEMPTY;		goto out;	}	/*	 * Delete reference to directory before purging	 * gnode.  If we crash in between, the directory	 * will be reattached to lost+found,	 */	if (dirremove(ndp) == 0)		goto out;	dp->g_nlink--;	dp->g_flag |= GCHG;	cacheinval(dp);	gput(dp);	dp = NULL;	/*	 * Truncate gnode.  The only stuff left	 * in the directory is "." and "..".  The	 * "." reference is inconsequential since	 * we're quashing it.  The ".." reference	 * has already been adjusted above.  We've	 * removed the "." reference and the reference	 * in the parent directory, but there may be	 * other hard links so decrement by 2 and	 * worry about them later.	 */	gp->g_nlink -= 2;	ufs_gtrunc(gp, (u_long)0, (struct ucred *) 0);	cacheinval(gp);out:	if (dp)		gput(dp);	gput(gp);}ufs_seek(gp, where)	struct gnode *gp;	int where;{	/*	 * this is a dummy routine because gfs semantics tell us that	 * if an operation is not supported, there is no function	 * in the mount ops.	 */	return(0);}

⌨️ 快捷键说明

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