/* Used to check for read/write/execute permissions on an inode. We use "fsuid" for this, letting us set arbitrary permissions for filesystem access without changing the "normal" uids which are used for other things.  */
int inode_permission(struct inode *inode, int mask)
/* Used to check for read/write/execute permissions on an inode. We use "fsuid" for this, letting us set arbitrary permissions for filesystem access without changing the "normal" uids which are used for other things.  */
int inode_permission(struct inode *inode, int mask)
{
	int retval;
	if (mask & MAY_WRITE) {
		umode_t mode = inode->i_mode;
		if (IS_RDONLY(inode) &&
		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
			return -EROFS;
		if (IS_IMMUTABLE(inode))
			return -EACCES;
	}
	if (inode->i_op->permission)
		retval = inode->i_op->permission(inode, mask);
	else
		retval = generic_permission(inode, mask, inode->i_op->check_acl);
	if (retval)
		return retval;
	retval = devcgroup_inode_permission(inode, mask);
	if (retval)
		return retval;
	return security_inode_permission(inode,
			mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
}