NetBSD/sys/kern/vfs_quotactl.c

310 lines
9.6 KiB
C
Raw Normal View History

/* $NetBSD: vfs_quotactl.c,v 1.6 2012/01/29 06:36:50 dholland Exp $ */
/*
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95
* From NetBSD: ufs_vfsops.c,v 1.42 2011/03/24 17:05:46 bouyer Exp
*/
/*
* Copyright (c) 1982, 1986, 1990, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Robert Elz at The University of Melbourne.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
* From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp
*/
/*
* Note that both of the copyrights above are moderately spurious;
* this code should almost certainly have the Copyright 2010 Manuel
* Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c.
* However, they're what was on the files this code was sliced out of.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.6 2012/01/29 06:36:50 dholland Exp $");
#include <sys/mount.h>
#include <sys/quotactl.h>
#include <quota/quotaprop.h>
static int
vfs_quotactl_getversion(struct mount *mp,
prop_dictionary_t cmddict, int q2type,
prop_array_t datas)
{
prop_array_t replies;
prop_dictionary_t data;
int q2version;
struct vfs_quotactl_args args;
int error;
KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
args.qc_type = QCT_GETVERSION;
args.u.getversion.qc_version_ret = &q2version;
error = VFS_QUOTACTL(mp, QUOTACTL_GETVERSION, &args);
if (error) {
return error;
}
data = prop_dictionary_create();
if (data == NULL) {
return ENOMEM;
}
if (!prop_dictionary_set_int8(data, "version", q2version)) {
prop_object_release(data);
return ENOMEM;
}
replies = prop_array_create();
if (replies == NULL) {
prop_object_release(data);
return ENOMEM;
}
if (!prop_array_add_and_rel(replies, data)) {
prop_object_release(data);
prop_object_release(replies);
return ENOMEM;
}
if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
prop_object_release(replies);
return ENOMEM;
}
return error;
}
static int
vfs_quotactl_quotaon(struct mount *mp,
prop_dictionary_t cmddict, int q2type,
prop_array_t datas)
{
struct vfs_quotactl_args args;
args.qc_type = QCT_PROPLIB;
args.u.proplib.qc_cmddict = cmddict;
args.u.proplib.qc_q2type = q2type;
args.u.proplib.qc_datas = datas;
return VFS_QUOTACTL(mp, QUOTACTL_QUOTAON, &args);
}
static int
vfs_quotactl_quotaoff(struct mount *mp,
prop_dictionary_t cmddict, int q2type,
prop_array_t datas)
{
struct vfs_quotactl_args args;
args.qc_type = QCT_PROPLIB;
args.u.proplib.qc_cmddict = cmddict;
args.u.proplib.qc_q2type = q2type;
args.u.proplib.qc_datas = datas;
return VFS_QUOTACTL(mp, QUOTACTL_QUOTAOFF, &args);
}
static int
vfs_quotactl_get(struct mount *mp,
prop_dictionary_t cmddict, int q2type,
prop_array_t datas)
{
struct vfs_quotactl_args args;
args.qc_type = QCT_PROPLIB;
args.u.proplib.qc_cmddict = cmddict;
args.u.proplib.qc_q2type = q2type;
args.u.proplib.qc_datas = datas;
return VFS_QUOTACTL(mp, QUOTACTL_GET, &args);
}
static int
vfs_quotactl_set(struct mount *mp,
prop_dictionary_t cmddict, int q2type,
prop_array_t datas)
{
struct vfs_quotactl_args args;
args.qc_type = QCT_PROPLIB;
args.u.proplib.qc_cmddict = cmddict;
args.u.proplib.qc_q2type = q2type;
args.u.proplib.qc_datas = datas;
return VFS_QUOTACTL(mp, QUOTACTL_SET, &args);
}
static int
vfs_quotactl_getall(struct mount *mp,
prop_dictionary_t cmddict, int q2type,
prop_array_t datas)
{
struct vfs_quotactl_args args;
args.qc_type = QCT_PROPLIB;
args.u.proplib.qc_cmddict = cmddict;
args.u.proplib.qc_q2type = q2type;
args.u.proplib.qc_datas = datas;
return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args);
}
static int
vfs_quotactl_clear(struct mount *mp,
prop_dictionary_t cmddict, int q2type,
prop_array_t datas)
{
struct vfs_quotactl_args args;
args.qc_type = QCT_PROPLIB;
args.u.proplib.qc_cmddict = cmddict;
args.u.proplib.qc_q2type = q2type;
args.u.proplib.qc_datas = datas;
return VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args);
}
static int
vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict)
{
int error;
const char *cmd, *type;
prop_array_t datas;
int q2type;
if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd))
return EINVAL;
if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type))
return EINVAL;
if (!strcmp(type, QUOTADICT_CLASS_USER)) {
q2type = QUOTA_CLASS_USER;
} else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) {
q2type = QUOTA_CLASS_GROUP;
} else {
/* XXX this is a bad errno for this case */
return EOPNOTSUPP;
}
datas = prop_dictionary_get(cmddict, "data");
if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY)
return EINVAL;
prop_object_retain(datas);
prop_dictionary_remove(cmddict, "data"); /* prepare for return */
if (strcmp(cmd, "get version") == 0) {
error = vfs_quotactl_getversion(mp, cmddict, q2type, datas);
} else if (strcmp(cmd, "quotaon") == 0) {
error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas);
} else if (strcmp(cmd, "quotaoff") == 0) {
error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas);
} else if (strcmp(cmd, "get") == 0) {
error = vfs_quotactl_get(mp, cmddict, q2type, datas);
} else if (strcmp(cmd, "set") == 0) {
error = vfs_quotactl_set(mp, cmddict, q2type, datas);
} else if (strcmp(cmd, "getall") == 0) {
error = vfs_quotactl_getall(mp, cmddict, q2type, datas);
} else if (strcmp(cmd, "clear") == 0) {
error = vfs_quotactl_clear(mp, cmddict, q2type, datas);
} else {
/* XXX this a bad errno for this case */
error = EOPNOTSUPP;
}
error = (prop_dictionary_set_int8(cmddict, "return",
error) ? 0 : ENOMEM);
prop_object_release(datas);
return error;
}
int
vfs_quotactl(struct mount *mp, prop_dictionary_t dict)
{
prop_dictionary_t cmddict;
prop_array_t commands;
prop_object_iterator_t iter;
int error;
error = quota_get_cmds(dict, &commands);
if (error) {
return error;
}
iter = prop_array_iterator(commands);
if (iter == NULL) {
return ENOMEM;
}
while ((cmddict = prop_object_iterator_next(iter)) != NULL) {
if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) {
/* XXX shouldn't this be an error? */
continue;
}
error = vfs_quotactl_cmd(mp, cmddict);
if (error) {
break;
}
}
prop_object_iterator_release(iter);
return error;
}