1*01e782f3Sdholland /* $NetBSD: quota_kernel.c,v 1.6 2014/06/28 22:27:50 dholland Exp $ */
259b296daSdholland /*-
359b296daSdholland * Copyright (c) 2012 The NetBSD Foundation, Inc.
459b296daSdholland * All rights reserved.
559b296daSdholland *
659b296daSdholland * This code is derived from software contributed to The NetBSD Foundation
759b296daSdholland * by David A. Holland.
859b296daSdholland *
959b296daSdholland * Redistribution and use in source and binary forms, with or without
1059b296daSdholland * modification, are permitted provided that the following conditions
1159b296daSdholland * are met:
1259b296daSdholland * 1. Redistributions of source code must retain the above copyright
1359b296daSdholland * notice, this list of conditions and the following disclaimer.
1459b296daSdholland * 2. Redistributions in binary form must reproduce the above copyright
1559b296daSdholland * notice, this list of conditions and the following disclaimer in the
1659b296daSdholland * documentation and/or other materials provided with the distribution.
1759b296daSdholland *
1859b296daSdholland * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1959b296daSdholland * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2059b296daSdholland * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2159b296daSdholland * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2259b296daSdholland * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2359b296daSdholland * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2459b296daSdholland * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2559b296daSdholland * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2659b296daSdholland * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2759b296daSdholland * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2859b296daSdholland * POSSIBILITY OF SUCH DAMAGE.
2959b296daSdholland */
3059b296daSdholland
3159b296daSdholland #include <sys/cdefs.h>
32*01e782f3Sdholland __RCSID("$NetBSD: quota_kernel.c,v 1.6 2014/06/28 22:27:50 dholland Exp $");
3359b296daSdholland
3459b296daSdholland #include <stdlib.h>
3559b296daSdholland #include <err.h>
3659b296daSdholland #include <errno.h>
3759b296daSdholland #include <limits.h>
3859b296daSdholland
3959b296daSdholland #include <quota.h>
4059b296daSdholland #include <sys/quotactl.h>
4159b296daSdholland
4259b296daSdholland #include "quotapvt.h"
4359b296daSdholland
4459b296daSdholland struct kernel_quotacursor {
4559b296daSdholland /* just wrap the kernel interface type */
4659b296daSdholland struct quotakcursor kcursor;
4759b296daSdholland };
4859b296daSdholland
4959b296daSdholland static int
__quota_kernel_stat(struct quotahandle * qh,struct quotastat * stat)5059b296daSdholland __quota_kernel_stat(struct quotahandle *qh, struct quotastat *stat)
5159b296daSdholland {
5259b296daSdholland struct quotactl_args args;
5359b296daSdholland
5459b296daSdholland args.qc_op = QUOTACTL_STAT;
55d2d6fa0aSdholland args.u.stat.qc_info = stat;
5659b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
5759b296daSdholland }
5859b296daSdholland
5959b296daSdholland const char *
__quota_kernel_getimplname(struct quotahandle * qh)6059b296daSdholland __quota_kernel_getimplname(struct quotahandle *qh)
6159b296daSdholland {
6259b296daSdholland static struct quotastat stat;
6359b296daSdholland
6459b296daSdholland if (__quota_kernel_stat(qh, &stat)) {
6559b296daSdholland return NULL;
6659b296daSdholland }
6759b296daSdholland return stat.qs_implname;
6859b296daSdholland }
6959b296daSdholland
7059b296daSdholland unsigned
__quota_kernel_getrestrictions(struct quotahandle * qh)7159b296daSdholland __quota_kernel_getrestrictions(struct quotahandle *qh)
7259b296daSdholland {
7359b296daSdholland struct quotastat stat;
7459b296daSdholland
7559b296daSdholland if (__quota_kernel_stat(qh, &stat)) {
7659b296daSdholland /* XXX no particularly satisfactory thing to do here */
7759b296daSdholland return 0;
7859b296daSdholland }
7959b296daSdholland return stat.qs_restrictions;
8059b296daSdholland }
8159b296daSdholland
82832d4ca7Sdholland int
__quota_kernel_getnumidtypes(struct quotahandle * qh)8359b296daSdholland __quota_kernel_getnumidtypes(struct quotahandle *qh)
8459b296daSdholland {
8559b296daSdholland struct quotastat stat;
8659b296daSdholland
8759b296daSdholland if (__quota_kernel_stat(qh, &stat)) {
8859b296daSdholland return 0;
8959b296daSdholland }
9059b296daSdholland return stat.qs_numidtypes;
9159b296daSdholland }
9259b296daSdholland
9359b296daSdholland const char *
__quota_kernel_idtype_getname(struct quotahandle * qh,int idtype)9459b296daSdholland __quota_kernel_idtype_getname(struct quotahandle *qh, int idtype)
9559b296daSdholland {
9659b296daSdholland static struct quotaidtypestat stat;
9759b296daSdholland struct quotactl_args args;
9859b296daSdholland
9959b296daSdholland args.qc_op = QUOTACTL_IDTYPESTAT;
10059b296daSdholland args.u.idtypestat.qc_idtype = idtype;
10159b296daSdholland args.u.idtypestat.qc_info = &stat;
10259b296daSdholland if (__quotactl(qh->qh_mountpoint, &args)) {
10359b296daSdholland return NULL;
10459b296daSdholland }
10559b296daSdholland return stat.qis_name;
10659b296daSdholland }
10759b296daSdholland
108832d4ca7Sdholland int
__quota_kernel_getnumobjtypes(struct quotahandle * qh)10959b296daSdholland __quota_kernel_getnumobjtypes(struct quotahandle *qh)
11059b296daSdholland {
11159b296daSdholland struct quotastat stat;
11259b296daSdholland
11359b296daSdholland if (__quota_kernel_stat(qh, &stat)) {
11459b296daSdholland return 0;
11559b296daSdholland }
11659b296daSdholland return stat.qs_numobjtypes;
11759b296daSdholland }
11859b296daSdholland
11959b296daSdholland const char *
__quota_kernel_objtype_getname(struct quotahandle * qh,int objtype)12059b296daSdholland __quota_kernel_objtype_getname(struct quotahandle *qh, int objtype)
12159b296daSdholland {
12259b296daSdholland static struct quotaobjtypestat stat;
12359b296daSdholland struct quotactl_args args;
12459b296daSdholland
12559b296daSdholland args.qc_op = QUOTACTL_OBJTYPESTAT;
12659b296daSdholland args.u.objtypestat.qc_objtype = objtype;
12759b296daSdholland args.u.objtypestat.qc_info = &stat;
12859b296daSdholland if (__quotactl(qh->qh_mountpoint, &args)) {
12959b296daSdholland return NULL;
13059b296daSdholland }
13159b296daSdholland return stat.qos_name;
13259b296daSdholland }
13359b296daSdholland
13459b296daSdholland int
__quota_kernel_objtype_isbytes(struct quotahandle * qh,int objtype)13559b296daSdholland __quota_kernel_objtype_isbytes(struct quotahandle *qh, int objtype)
13659b296daSdholland {
13759b296daSdholland struct quotaobjtypestat stat;
13859b296daSdholland struct quotactl_args args;
13959b296daSdholland
14059b296daSdholland args.qc_op = QUOTACTL_OBJTYPESTAT;
14159b296daSdholland args.u.objtypestat.qc_objtype = objtype;
14259b296daSdholland args.u.objtypestat.qc_info = &stat;
14359b296daSdholland if (__quotactl(qh->qh_mountpoint, &args)) {
14459b296daSdholland return 0;
14559b296daSdholland }
14659b296daSdholland return stat.qos_isbytes;
14759b296daSdholland }
14859b296daSdholland
14959b296daSdholland int
__quota_kernel_quotaon(struct quotahandle * qh,int idtype)15059b296daSdholland __quota_kernel_quotaon(struct quotahandle *qh, int idtype)
15159b296daSdholland {
15259b296daSdholland struct quotactl_args args;
15359b296daSdholland const char *file;
15459b296daSdholland char path[PATH_MAX];
15559b296daSdholland
15659b296daSdholland /*
15759b296daSdholland * Note that while it is an error to call quotaon on something
15859b296daSdholland * that isn't a volume with old-style quotas that expects
15959b296daSdholland * quotaon to be called, it's not our responsibility to check
16059b296daSdholland * for that; the filesystem will. Also note that it is not an
16159b296daSdholland * error to call quotaon repeatedly -- apparently this is to
16259b296daSdholland * permit changing the quota file in use on the fly or
16359b296daSdholland * something. So all we need to do here is ask the oldfiles
16459b296daSdholland * code if the mount option was set in fstab and fetch back
16559b296daSdholland * the filename.
16659b296daSdholland */
16759b296daSdholland
16859b296daSdholland file = __quota_oldfiles_getquotafile(qh, idtype, path, sizeof(path));
16959b296daSdholland if (file == NULL) {
17059b296daSdholland /*
17159b296daSdholland * This idtype (or maybe any idtype) was not enabled
17259b296daSdholland * in fstab.
17359b296daSdholland */
17459b296daSdholland errno = ENXIO;
17559b296daSdholland return -1;
17659b296daSdholland }
17759b296daSdholland
17859b296daSdholland args.qc_op = QUOTACTL_QUOTAON;
17959b296daSdholland args.u.quotaon.qc_idtype = idtype;
18059b296daSdholland args.u.quotaon.qc_quotafile = file;
18159b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
18259b296daSdholland }
18359b296daSdholland
18459b296daSdholland int
__quota_kernel_quotaoff(struct quotahandle * qh,int idtype)18559b296daSdholland __quota_kernel_quotaoff(struct quotahandle *qh, int idtype)
18659b296daSdholland {
18759b296daSdholland struct quotactl_args args;
18859b296daSdholland
18959b296daSdholland args.qc_op = QUOTACTL_QUOTAOFF;
19059b296daSdholland args.u.quotaoff.qc_idtype = idtype;
19159b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
19259b296daSdholland }
19359b296daSdholland
19459b296daSdholland int
__quota_kernel_get(struct quotahandle * qh,const struct quotakey * qk,struct quotaval * qv)19559b296daSdholland __quota_kernel_get(struct quotahandle *qh, const struct quotakey *qk,
19659b296daSdholland struct quotaval *qv)
19759b296daSdholland {
19859b296daSdholland struct quotactl_args args;
19959b296daSdholland
20059b296daSdholland args.qc_op = QUOTACTL_GET;
20159b296daSdholland args.u.get.qc_key = qk;
202d2d6fa0aSdholland args.u.get.qc_val = qv;
20359b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
20459b296daSdholland }
20559b296daSdholland
20659b296daSdholland int
__quota_kernel_put(struct quotahandle * qh,const struct quotakey * qk,const struct quotaval * qv)20759b296daSdholland __quota_kernel_put(struct quotahandle *qh, const struct quotakey *qk,
20859b296daSdholland const struct quotaval *qv)
20959b296daSdholland {
21059b296daSdholland struct quotactl_args args;
21159b296daSdholland
21259b296daSdholland args.qc_op = QUOTACTL_PUT;
21359b296daSdholland args.u.put.qc_key = qk;
21459b296daSdholland args.u.put.qc_val = qv;
21559b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
21659b296daSdholland }
21759b296daSdholland
21859b296daSdholland int
__quota_kernel_delete(struct quotahandle * qh,const struct quotakey * qk)21959b296daSdholland __quota_kernel_delete(struct quotahandle *qh, const struct quotakey *qk)
22059b296daSdholland {
22159b296daSdholland struct quotactl_args args;
22259b296daSdholland
223*01e782f3Sdholland args.qc_op = QUOTACTL_DEL;
224*01e782f3Sdholland args.u.del.qc_key = qk;
22559b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
22659b296daSdholland }
22759b296daSdholland
22859b296daSdholland struct kernel_quotacursor *
__quota_kernel_cursor_create(struct quotahandle * qh)22959b296daSdholland __quota_kernel_cursor_create(struct quotahandle *qh)
23059b296daSdholland {
23159b296daSdholland struct quotactl_args args;
23259b296daSdholland struct kernel_quotacursor *cursor;
23359b296daSdholland int sverrno;
23459b296daSdholland
23559b296daSdholland cursor = malloc(sizeof(*cursor));
23659b296daSdholland if (cursor == NULL) {
23759b296daSdholland return NULL;
23859b296daSdholland }
23959b296daSdholland
24059b296daSdholland args.qc_op = QUOTACTL_CURSOROPEN;
24159b296daSdholland args.u.cursoropen.qc_cursor = &cursor->kcursor;
24259b296daSdholland if (__quotactl(qh->qh_mountpoint, &args)) {
24359b296daSdholland sverrno = errno;
24459b296daSdholland free(cursor);
24559b296daSdholland errno = sverrno;
24659b296daSdholland return NULL;
24759b296daSdholland }
24859b296daSdholland return cursor;
24959b296daSdholland }
25059b296daSdholland
25159b296daSdholland void
__quota_kernel_cursor_destroy(struct quotahandle * qh,struct kernel_quotacursor * cursor)25259b296daSdholland __quota_kernel_cursor_destroy(struct quotahandle *qh,
25359b296daSdholland struct kernel_quotacursor *cursor)
25459b296daSdholland {
25559b296daSdholland struct quotactl_args args;
25659b296daSdholland
25759b296daSdholland args.qc_op = QUOTACTL_CURSORCLOSE;
25859b296daSdholland args.u.cursorclose.qc_cursor = &cursor->kcursor;
25959b296daSdholland if (__quotactl(qh->qh_mountpoint, &args)) {
26059b296daSdholland /* XXX should we really print from inside the library? */
26159b296daSdholland warn("__quotactl cursorclose");
26259b296daSdholland }
26359b296daSdholland free(cursor);
26459b296daSdholland }
26559b296daSdholland
26659b296daSdholland int
__quota_kernel_cursor_skipidtype(struct quotahandle * qh,struct kernel_quotacursor * cursor,int idtype)26759b296daSdholland __quota_kernel_cursor_skipidtype(struct quotahandle *qh,
26859b296daSdholland struct kernel_quotacursor *cursor,
269832d4ca7Sdholland int idtype)
27059b296daSdholland {
27159b296daSdholland struct quotactl_args args;
27259b296daSdholland
27359b296daSdholland args.qc_op = QUOTACTL_CURSORSKIPIDTYPE;
27459b296daSdholland args.u.cursorskipidtype.qc_cursor = &cursor->kcursor;
27559b296daSdholland args.u.cursorskipidtype.qc_idtype = idtype;
27659b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
27759b296daSdholland }
27859b296daSdholland
27959b296daSdholland int
__quota_kernel_cursor_get(struct quotahandle * qh,struct kernel_quotacursor * cursor,struct quotakey * key,struct quotaval * val)28059b296daSdholland __quota_kernel_cursor_get(struct quotahandle *qh,
28159b296daSdholland struct kernel_quotacursor *cursor,
28259b296daSdholland struct quotakey *key, struct quotaval *val)
28359b296daSdholland {
28459b296daSdholland int ret;
28559b296daSdholland
28659b296daSdholland ret = __quota_kernel_cursor_getn(qh, cursor, key, val, 1);
28759b296daSdholland if (ret < 0) {
28859b296daSdholland return -1;
28959b296daSdholland }
29059b296daSdholland return 0;
29159b296daSdholland }
29259b296daSdholland
29359b296daSdholland int
__quota_kernel_cursor_getn(struct quotahandle * qh,struct kernel_quotacursor * cursor,struct quotakey * keys,struct quotaval * vals,unsigned maxnum)29459b296daSdholland __quota_kernel_cursor_getn(struct quotahandle *qh,
29559b296daSdholland struct kernel_quotacursor *cursor,
29659b296daSdholland struct quotakey *keys, struct quotaval *vals,
29759b296daSdholland unsigned maxnum)
29859b296daSdholland {
29959b296daSdholland struct quotactl_args args;
30059b296daSdholland unsigned ret;
30159b296daSdholland
30231f4a06fSdholland if (maxnum > INT_MAX) {
30331f4a06fSdholland /* joker, eh? */
30431f4a06fSdholland errno = EINVAL;
30531f4a06fSdholland return -1;
30631f4a06fSdholland }
30731f4a06fSdholland
30859b296daSdholland args.qc_op = QUOTACTL_CURSORGET;
30959b296daSdholland args.u.cursorget.qc_cursor = &cursor->kcursor;
31059b296daSdholland args.u.cursorget.qc_keys = keys;
31159b296daSdholland args.u.cursorget.qc_vals = vals;
31259b296daSdholland args.u.cursorget.qc_maxnum = maxnum;
31359b296daSdholland args.u.cursorget.qc_ret = &ret;
31431f4a06fSdholland if (__quotactl(qh->qh_mountpoint, &args) < 0) {
31531f4a06fSdholland return -1;
31631f4a06fSdholland }
31731f4a06fSdholland return ret;
31859b296daSdholland }
31959b296daSdholland
32059b296daSdholland int
__quota_kernel_cursor_atend(struct quotahandle * qh,struct kernel_quotacursor * cursor)32159b296daSdholland __quota_kernel_cursor_atend(struct quotahandle *qh,
32259b296daSdholland struct kernel_quotacursor *cursor)
32359b296daSdholland {
32459b296daSdholland struct quotactl_args args;
32559b296daSdholland int ret;
32659b296daSdholland
32759b296daSdholland args.qc_op = QUOTACTL_CURSORATEND;
32859b296daSdholland args.u.cursoratend.qc_cursor = &cursor->kcursor;
32959b296daSdholland args.u.cursoratend.qc_ret = &ret;
33059b296daSdholland if (__quotactl(qh->qh_mountpoint, &args)) {
33159b296daSdholland /*
33259b296daSdholland * Return -1 so naive callers, who test for the return
33359b296daSdholland * value being nonzero, stop iterating, and
33459b296daSdholland * sophisticated callers can tell an error from
33559b296daSdholland * end-of-data.
33659b296daSdholland */
33759b296daSdholland return -1;
33859b296daSdholland }
33959b296daSdholland return ret;
34059b296daSdholland }
34159b296daSdholland
34259b296daSdholland int
__quota_kernel_cursor_rewind(struct quotahandle * qh,struct kernel_quotacursor * cursor)34359b296daSdholland __quota_kernel_cursor_rewind(struct quotahandle *qh,
34459b296daSdholland struct kernel_quotacursor *cursor)
34559b296daSdholland {
34659b296daSdholland struct quotactl_args args;
34759b296daSdholland
34859b296daSdholland args.qc_op = QUOTACTL_CURSORREWIND;
34959b296daSdholland args.u.cursorrewind.qc_cursor = &cursor->kcursor;
35059b296daSdholland return __quotactl(qh->qh_mountpoint, &args);
35159b296daSdholland }
352