Ejemplo n.º 1
0
/*
 * NAME:	iOpenAccess()
 *
 * FUNCTION:	check access permissions before an open
 *		called by jfs_open() and jfs_create().
 *
 * PARAMETER:	ip	- inode in question
 *		flag	- permissions to check
 *		crp	- credential
 *
 * RETURN:
 */
int32 iOpenAccess(
	inode_t		*ip,	/* inode to check access for */
	int32		flag,	/* open flags */
	struct ucred	*crp)
{
	int32 rc = 0;
	int32 mode;
	struct gnode *gp = IP2GP(ip);		

	if (((flag & OPEN_FLAGS_LARGEFILE) == 0) &&
	    (ip->i_size > 0x7fffffff))
		return ERROR_ACCESS_DENIED;

	/* set up mode for call to iAccess  */
	switch (flag & (OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY))
	{
	    case (OPEN_ACCESS_READWRITE):
		mode = (IREAD|IWRITE);
		break;

	    case (OPEN_ACCESS_WRITEONLY):
		mode = IWRITE;
		break;

	    default:
		mode = IREAD;
	}

	/* check for sharing violation */
	if ((mode & IREAD) && (gp->gn_drcnt))
		rc = ETXTBSY;
	else if ((mode & IWRITE) && (gp->gn_dwcnt))
		rc = ETXTBSY;
	else if (gp->gn_flags & GNF_NSHARE)
		rc = ETXTBSY;

	/* check permissions */
	else
		rc = iAccess(ip, mode, crp);

	return rc;
}
Ejemplo n.º 2
0
/*
 * NAME:	jfs_mknod(dvp, name, mode, dev, crp)
 *
 * FUNCTION:	make a new object in directory <dvp> with mode = <mode>,
 *		name = <pname>, and rdev = <dev>.
 *
 * PARAMETER:	dvp 	- directory vnode
 *		name	- name of new object
 *		mode	- create mode (rwxrwxrwx).
 *		dev	- new device number if block/character-special file
 *		crp	- credential
 *
 * RETURN:	Errors from subroutines
 *
 * note: JFS allows mknod() to create a special file.
 * XPG4.2: the only portable use of mknod() is to create a FIFO-special file
 * with mode = S_IFIFO and dev = 0.
 */
jfs_mknod(
	struct vnode	*dvp,
	caddr_t		name,
	mode_t		mode,
	dev_t		dev,
	struct ucred	*crp)
{
	int32	rc;
	int32	tid;
	inode_t	*dip = VP2IP(dvp);
	inode_t *ip;
	ino_t	ino;
	component_t	dname;
	struct vfs	*vfsp = dvp->v_vfsp;
	btstack_t	btstack;
	inode_t		*iplist[2];

	/* JFS does NOT support mknod() of directory */
	if ((mode & IFMT) == IFDIR)
		return EISDIR;
		
	if ((mode & IFMT) != IFIFO && (mode & IFMT) != IFSOCK)
		if (rc = privcheck_cr(DEV_CONFIG, crp))
			return rc;

	IWRITE_LOCK(dip);

	txBegin(dip->i_ipmnt, &tid, 0);

	/* validate search+write permission on parent directory */
	if (rc = iAccess(dip, IEXEC|IWRITE, crp))
		goto out1;

	/*
	 * scan parent directory for entry/freespace
	 * (dtSearch() returns parent directory page pinned)
	 */
	dname.name = name;
	dname.namlen = strlen(name);
	if (rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))
		goto out1;

	/*
	 * allocate in-memory+on-disk inode:
	 * (iAlloc() returns new, locked inode)
	 */
	if (rc = iAlloc(vfsp, dip, mode, &ip, crp))
	{	
		/* release parent directory page */
		BT_PUTSEARCH(&btstack);

		goto out1;
	}

	/*
	 * create entry in parent directory
	 * (dtInsert() releases parent directory page)
	 */
	ino = ip->i_number;
	if (rc = dtInsert(tid, dip, &dname, &ino, &btstack))
	{
		/* discard the new inode */
		ip->i_nlink = 0;

		goto out2;
	}

	/*
	 * fo a block or character special file, the passed-in device number
	 * needs to be set into the inode's device field and the gnode's
	 * "real device" field.
	 */
	if ((ip->i_mode & IFMT) == IFBLK || (ip->i_mode & IFMT) == IFCHR)
	{
		ip->i_rdev = dev;
		IP2GP(ip)->gn_rdev = dev;
	}

	imark(ip, IACC|ICHG|IUPD|IFSYNC);	

	/* update parent directory inode */
	imark(dip, ICHG|IUPD|IFSYNC);

	/*
	 * insert entry for the new file to dnlc
	 */
	ncEnter(dip->i_ipimap, dip->i_number, &dname, ino, NULL);

	iplist[0] = dip;
	iplist[1] = ip;
	rc = txCommit(tid, 2, &iplist[0], 0);

out2:
	IWRITE_UNLOCK(ip);

	ICACHE_LOCK();
	iput(ip, vfsp);
	ICACHE_UNLOCK();

out1:
	IWRITE_UNLOCK(dip);

	txEnd(tid);

	return rc;
}