예제 #1
0
static int
devfs_vop_setattr(struct vop_setattr_args *ap)
{
	struct devfs_node *node = DEVFS_NODE(ap->a_vp);
	struct vattr *vap;
	uid_t cur_uid;
	gid_t cur_gid;
	mode_t cur_mode;
	int error = 0;

	if (!devfs_node_is_accessible(node))
		return ENOENT;
	node_sync_dev_get(node);

	lockmgr(&devfs_lock, LK_EXCLUSIVE);

	vap = ap->a_vap;

	if ((vap->va_uid != (uid_t)VNOVAL) || (vap->va_gid != (gid_t)VNOVAL)) {
		cur_uid = node->uid;
		cur_gid = node->gid;
		cur_mode = node->mode;
		error = vop_helper_chown(ap->a_vp, vap->va_uid, vap->va_gid,
		    ap->a_cred, &cur_uid, &cur_gid, &cur_mode);
		if (error)
			goto out;

		if (node->uid != cur_uid || node->gid != cur_gid) {
			node->uid = cur_uid;
			node->gid = cur_gid;
			node->mode = cur_mode;
		}
	}

	if (vap->va_mode != (mode_t)VNOVAL) {
		cur_mode = node->mode;
		error = vop_helper_chmod(ap->a_vp, vap->va_mode, ap->a_cred,
		    node->uid, node->gid, &cur_mode);
		if (error == 0 && node->mode != cur_mode) {
			node->mode = cur_mode;
		}
	}

out:
	node_sync_dev_set(node);
	nanotime(&node->ctime);
	lockmgr(&devfs_lock, LK_RELEASE);

	return error;
}
예제 #2
0
/*
 * Change access mode on the given vnode.
 * Caller should execute tmpfs_update on vp after a successful execution.
 * The vnode must be locked on entry and remain locked on exit.
 */
int
tmpfs_chmod(struct vnode *vp, mode_t vamode, struct ucred *cred)
{
	struct tmpfs_node *node;
	mode_t cur_mode;
	int error;

	KKASSERT(vn_islocked(vp));

	node = VP_TO_TMPFS_NODE(vp);

	/* Disallow this operation if the file system is mounted read-only. */
	if (vp->v_mount->mnt_flag & MNT_RDONLY)
		return EROFS;

	/* Immutable or append-only files cannot be modified, either. */
	if (node->tn_flags & (IMMUTABLE | APPEND))
		return EPERM;

	cur_mode = node->tn_mode;
	error = vop_helper_chmod(vp, vamode, cred, node->tn_uid, node->tn_gid,
				 &cur_mode);

	if (error == 0 &&
	    (node->tn_mode & ALLPERMS) != (cur_mode & ALLPERMS)) {
		TMPFS_NODE_LOCK(node);
		node->tn_mode &= ~ALLPERMS;
		node->tn_mode |= cur_mode & ALLPERMS;

		node->tn_status |= TMPFS_NODE_CHANGED;
		TMPFS_NODE_UNLOCK(node);
	}

	KKASSERT(vn_islocked(vp));

	return 0;
}