Esempio n. 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;
}
Esempio n. 2
0
/*
 * Change ownership of the given vnode.  At least one of uid or gid must
 * be different than VNOVAL.  If one is set to that value, the attribute
 * is unchanged.
 * 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_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred)
{
	mode_t cur_mode;
	uid_t cur_uid;
	gid_t cur_gid;
	struct tmpfs_node *node;
	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_uid = node->tn_uid;
	cur_gid = node->tn_gid;
	cur_mode = node->tn_mode;
	error = vop_helper_chown(vp, uid, gid, cred,
				 &cur_uid, &cur_gid, &cur_mode);

	if (error == 0) {
		TMPFS_NODE_LOCK(node);
		if (cur_uid != node->tn_uid ||
		    cur_gid != node->tn_gid ||
		    cur_mode != node->tn_mode) {
			node->tn_uid = cur_uid;
			node->tn_gid = cur_gid;
			node->tn_mode = cur_mode;
			node->tn_status |= TMPFS_NODE_CHANGED;
		}
		TMPFS_NODE_UNLOCK(node);
	}

	return error;
}